From 0f958cc2d66590e21d0978693c6ab62e50188f51 Mon Sep 17 00:00:00 2001 From: jkriege2 Date: Sun, 3 Jul 2022 20:30:12 +0200 Subject: [PATCH] - JKQTMathText: IMPROVED/breaking: refactored symbol node JKQTMathTextSymbolNode and changed font-lookup! - JKQTMathText: IMPROVED/NEW/breaking: refactored whitespace-processing node JKQTMathTextWhitespaceNode, now all major LaTeX whitespace commands are supported properly --- doc/dox/whatsnew.dox | 4 +- examples/jkqtmathtext_test/testform.cpp | 34 +- examples/jkqtmathtext_test/testform.ui | 661 +++--- .../jkqtplot_test/TestWidgetBarcharts.cpp | 4 +- lib/jkqtmathtext/CMakeLists.txt | 3 + lib/jkqtmathtext/jkqtmathtext.cpp | 767 +++--- lib/jkqtmathtext/jkqtmathtext.h | 66 +- lib/jkqtmathtext/jkqtmathtexttools.cpp | 55 +- lib/jkqtmathtext/jkqtmathtexttools.h | 34 +- .../nodes/jkqtmathtextsymbolnode.cpp | 2093 +++++++---------- .../nodes/jkqtmathtextsymbolnode.h | 221 +- .../nodes/jkqtmathtexttextnode.cpp | 21 +- lib/jkqtmathtext/nodes/jkqtmathtexttextnode.h | 12 - .../nodes/jkqtmathtextwhitespacenode.cpp | 211 ++ .../nodes/jkqtmathtextwhitespacenode.h | 115 + 15 files changed, 2204 insertions(+), 2097 deletions(-) create mode 100644 lib/jkqtmathtext/nodes/jkqtmathtextwhitespacenode.cpp create mode 100644 lib/jkqtmathtext/nodes/jkqtmathtextwhitespacenode.h diff --git a/doc/dox/whatsnew.dox b/doc/dox/whatsnew.dox index 805883ac38..cf64fd63f7 100644 --- a/doc/dox/whatsnew.dox +++ b/doc/dox/whatsnew.dox @@ -40,7 +40,9 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
  • IMPROVED: added x-correction for sub/superscript above/below/besides integrals
  • IMPROVED: rendering of sqrt
  • IMPROVED: rendering and size calculation of decorations
  • -
  • remove/breaking: \v[a-zA-Z] and shorthand for \vec{a-zA-Z} was removed, implementation of \bbR,\bbC,... changed
  • +
  • IMPROVED/breaking: refactored symbol node JKQTMathTextSymbolNode and changed font-lookup!
  • +
  • IMPROVED/NEW/breaking: refactored whitespace-processing node JKQTMathTextWhitespaceNode, now all major LaTeX whitespace commands are supported properly
  • +
  • REMOVED/breaking: \v[a-zA-Z] and shorthand for \vec{a-zA-Z} was removed, implementation of \bbR,\bbC,... changed
  • NEW: now supports new decoration instructions: \cancel, \xcancel, \bcancel, \sout, \ocirc, \widetilde, \widehat, \breve
  • NEW: reworked drawing of decorations: improved appearance and positioning!
  • NEW: reworked code structure: broke up large, single CPP-files into several smaller files!
  • diff --git a/examples/jkqtmathtext_test/testform.cpp b/examples/jkqtmathtext_test/testform.cpp index 45ce7f86c6..437d550e2e 100644 --- a/examples/jkqtmathtext_test/testform.cpp +++ b/examples/jkqtmathtext_test/testform.cpp @@ -11,6 +11,7 @@ #include "jkqtmathtext/nodes/jkqtmathtextsqrtnode.h" #include "jkqtmathtext/nodes/jkqtmathtextsubsupernode.h" #include "jkqtmathtext/nodes/jkqtmathtextsymbolnode.h" +#include "jkqtmathtext/nodes/jkqtmathtextwhitespacenode.h" TestForm::TestForm(QWidget *parent) : @@ -21,6 +22,19 @@ TestForm::TestForm(QWidget *parent) : 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("math: simple relations", "$a{\\leq}b$, $a{\\geq}b$, $a{\\equiv}b$, $a=b$, $a{\\neq}b$, $ab$"); + const auto wsExample=[](const QStringList& spaces, const QString before, const QString& after)->QString { + QString s; + for (int i=0; icmbTestset->addItem("text: whitespaces arrows", "text: "+wsExample(whitespaces, "\\rightarrow", "\\leftarrow")); + ui->cmbTestset->addItem("text: whitespaces fg", "text: "+wsExample(whitespaces, "f", "g")); + ui->cmbTestset->addItem("math: whitespaces arrows", "math: "+wsExample(whitespaces, "$\\rightarrow", "\\leftarrow$")); + ui->cmbTestset->addItem("math: whitespaces fg", "math: "+wsExample(whitespaces, "$f", "g$")); 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$"); @@ -212,7 +226,7 @@ TestForm::TestForm(QWidget *parent) : ui->cmbEncodingSerifMath->setCurrentIndex(static_cast(mt.getFontEncodingMathRoman())); ui->cmbUnicodeSansMath->setCurrentFont(QFont(mt.getFontMathSans())); ui->cmbEncodingSansMath->setCurrentIndex(static_cast(mt.getFontEncodingMathSans())); - ui->cmbUnicodeFixed->setCurrentFont(QFont(mt.getFontTypewriter())); + ui->cmbUnicodeTypewriter->setCurrentFont(QFont(mt.getFontTypewriter())); ui->cmbEncodingTypewriter->setCurrentIndex(static_cast(mt.getFontEncodingTypewriter())); ui->cmbCaligraphic->setCurrentFont(QFont(mt.getFontCaligraphic())); ui->cmbEncodingCaligraphic->setCurrentIndex(static_cast(mt.getFontEncodingCaligraphic())); @@ -222,10 +236,10 @@ TestForm::TestForm(QWidget *parent) : ui->cmbEncodingFraktur->setCurrentIndex(static_cast(mt.getFontEncodingFraktur())); ui->cmbUnicodeBlackboard->setCurrentFont(QFont(mt.getFontBlackboard())); ui->cmbEncodingBlackboard->setCurrentIndex(static_cast(mt.getFontEncodingBlackboard())); - ui->cmbUnicodeSymbol->setCurrentFont(QFont(mt.getSymbolfontSymbol(JKQTMathTextEnvironmentFont::MTEroman))); - ui->cmbEncodingSymbol->setCurrentIndex(static_cast(mt.getSymbolfontEncodingSymbol(JKQTMathTextEnvironmentFont::MTEroman))); - ui->cmbUnicodeGreek->setCurrentFont(QFont(mt.getSymbolfontGreek(JKQTMathTextEnvironmentFont::MTEroman))); - ui->cmbEncodingGreek->setCurrentIndex(static_cast(mt.getSymbolfontEncodingGreek(JKQTMathTextEnvironmentFont::MTEroman))); + ui->cmbUnicodeSymbol->setCurrentFont(QFont(mt.getFallbackFontSymbols())); + ui->cmbEncodingSymbol->setCurrentIndex(static_cast(mt.getFontEncodingFallbackFontSymbols())); + ui->cmbUnicodeGreek->setCurrentFont(QFont(mt.getFallbackFontGreek())); + ui->cmbEncodingGreek->setCurrentIndex(static_cast(mt.getFontEncodingFallbackFontGreek())); ui->chkSimulateBlackboard->setChecked(mt.isFontBlackboardSimulated()); @@ -250,7 +264,7 @@ TestForm::TestForm(QWidget *parent) : connect(ui->cmbUnicodeSansMath, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMath())); connect(ui->cmbEncodingSans, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMath())); connect(ui->cmbEncodingSansMath, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMath())); - connect(ui->cmbUnicodeFixed, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMath())); + connect(ui->cmbUnicodeTypewriter, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMath())); connect(ui->cmbUnicodeGreek, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMath())); connect(ui->cmbUnicodeSerif, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMath())); connect(ui->cmbUnicodeSerifMath, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMath())); @@ -393,7 +407,7 @@ QTreeWidgetItem *TestForm::createTree(JKQTMathTextNode *node, QTreeWidgetItem* p } else if (symN) { name=QString("MTSymbolNode: \'%1\' (addWhite: %2, subsuper=%3)").arg(symN->getSymbolName()).arg(symN->getAddWhitespace()).arg(symN->isSubSuperscriptAboveBelowNode()); } else if (spN) { - name=QString("MTWhitespaceNode :\'%1\'").arg(txtN->getText()); + name=QString("MTWhitespaceNode :type=%1, count=%2").arg(spN->Type2String(spN->getWhitespaceType())).arg(spN->getWhitespaceCount()); } else if (txtN) { name=QString("MTTextNode: \'%1\'").arg(txtN->getText()); @@ -468,13 +482,13 @@ void TestForm::updateMath() mt.setFontSans(ui->cmbUnicodeSans->currentFont().family(), static_cast(ui->cmbEncodingSans->currentIndex())); mt.setFontMathRoman(ui->cmbUnicodeSerifMath->currentFont().family(), static_cast(ui->cmbEncodingSerifMath->currentIndex())); mt.setFontMathSans(ui->cmbUnicodeSansMath->currentFont().family(), static_cast(ui->cmbEncodingSansMath->currentIndex())); - mt.setFontTypewriter(ui->cmbUnicodeFixed->currentFont().family(), static_cast(ui->cmbEncodingTypewriter->currentIndex())); + mt.setFontTypewriter(ui->cmbUnicodeTypewriter->currentFont().family(), static_cast(ui->cmbEncodingTypewriter->currentIndex())); mt.setFontCaligraphic(ui->cmbCaligraphic->currentFont().family(), static_cast(ui->cmbEncodingCaligraphic->currentIndex())); mt.setFontScript(ui->cmbScript->currentFont().family(), static_cast(ui->cmbEncodingScript->currentIndex())); mt.setFontFraktur(ui->cmbUnicodeFraktur->currentFont().family(), static_cast(ui->cmbEncodingFraktur->currentIndex())); mt.setFontBlackboard(ui->cmbUnicodeBlackboard->currentFont().family(), static_cast(ui->cmbEncodingBlackboard->currentIndex())); - mt.setSymbolfontSymbol(ui->cmbUnicodeSymbol->currentFont().family(), static_cast(ui->cmbEncodingSymbol->currentIndex())); - mt.setSymbolfontGreek(ui->cmbUnicodeGreek->currentFont().family(), static_cast(ui->cmbEncodingGreek->currentIndex())); + mt.setFallbackFontSymbols(ui->cmbUnicodeSymbol->currentFont().family(), static_cast(ui->cmbEncodingSymbol->currentIndex())); + mt.setFallbackFontGreek(ui->cmbUnicodeGreek->currentFont().family(), static_cast(ui->cmbEncodingGreek->currentIndex())); } else if (ui->cmbFont->currentIndex()==5 || ui->cmbFont->currentIndex()==6) { mt.setFontRoman(QGuiApplication::font().family()); } else if (ui->cmbFont->currentIndex()==7) { diff --git a/examples/jkqtmathtext_test/testform.ui b/examples/jkqtmathtext_test/testform.ui index 063eec81f9..b67e7e41f4 100644 --- a/examples/jkqtmathtext_test/testform.ui +++ b/examples/jkqtmathtext_test/testform.ui @@ -144,70 +144,25 @@ - - - - Symbol/Unicode fonts: - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - blackboard: - - - - symbol: + fallback-greek: - - - - - - - - - - - - - - - - + + - roman: + sans: - - - - + + + + 2 - - - - WinSymbol @@ -220,20 +175,67 @@ - Unicode Limited - - - - - Standard + Latin1 - - + + + + + + + + + - sans: + Symbol/Unicode fonts: + + + + + + + + WinSymbol + + + + + Unicode + + + + + Latin1 + + + + + + + + + WinSymbol + + + + + Unicode + + + + + Latin-1 + + + + + + + + @@ -254,39 +256,7 @@ - Unicode Limited - - - - - Standard - - - - - - - - 2 - - - - WinSymbol - - - - - Unicode - - - - - Unicode Limited - - - - - Standard + Latin1 @@ -308,23 +278,40 @@ - Unicode Limited - - - - - Standard + Latin1 - - - - + + + + blackboard: + + + + 0 + + + + WinSymbol + + + + + Unicode + + + + + Latin1 + + + + @@ -332,258 +319,8 @@ - - - - - WinSymbol - - - - - Unicode - - - - - Unicode Limited - - - - - Standard - - - - - - - - greek: - - - - - - - simulate blackboard - - - - - - - fraktur: - - - - - - - - - - - - - - 1 - - - - WinSymbol - - - - - Unicode - - - - - Unicode Limited - - - - - Standard - - - - - - - - caligraphic: - - - - - - - - - - - - - - 3 - - - - WinSymbol - - - - - Unicode - - - - - Unicode Limited - - - - - Standard - - - - - - - - script: - - - - - - - - - - - - - 3 - - - - WinSymbol - - - - - Unicode - - - - - Unicode Limited - - - - - Standard - - - - - - - - typewriter: - - - - - - - - - - - - - - 3 - - - - WinSymbol - - - - - Unicode - - - - - Unicode Limited - - - - - Standard - - - - - - - - math- roman: - - - - - - - - - - - - - - 2 - - - - WinSymbol - - - - - Unicode - - - - - Unicode Limited - - - - - Standard - - - - - - - - math-sans: - - - - - + @@ -606,14 +343,222 @@ - Unicode Limited + Latin1 + + + + + + + + -1 + + + + WinSymbol - Standard + Unicode + + + Latin1 + + + + + + + + 1 + + + + WinSymbol + + + + + Unicode + + + + + Latin1 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + script: + + + + + + + math-sans: + + + + + + + + + + + + + + + + + + + + + -1 + + + + WinSymbol + + + + + Unicode + + + + + Latin1 + + + + + + + + + + + + + + + 0 + + + + WinSymbol + + + + + Unicode + + + + + Latin1 + + + + + + + + caligraphic: + + + + + + + simulate blackboard + + + + + + + typewriter: + + + + + + + math- roman: + + + + + + + fraktur: + + + + + + + + + + + + + + + + + + + + + roman: + + + + + + + + + + + + + + + + + + + + + fallback-symbol: + diff --git a/examples/jkqtplot_test/TestWidgetBarcharts.cpp b/examples/jkqtplot_test/TestWidgetBarcharts.cpp index e7506e7d1c..b2587ea3a0 100644 --- a/examples/jkqtplot_test/TestWidgetBarcharts.cpp +++ b/examples/jkqtplot_test/TestWidgetBarcharts.cpp @@ -112,7 +112,7 @@ TestWidgetBarcharts::TestWidgetBarcharts(QWidget *parent) : spinBarLabelAngel=new QSpinBox(this); spinBarLabelAngel->setPrefix(tr("rotation angel: ")); - spinBarLabelAngel->setSuffix(QLatin1String("\xB0")); + spinBarLabelAngel->setSuffix(QChar(0xB0)); spinBarLabelAngel->setRange(-180,180); spinBarLabelAngel->setValue(0); spinBarLabelAngel->setSingleStep(15); @@ -121,7 +121,7 @@ TestWidgetBarcharts::TestWidgetBarcharts(QWidget *parent) : spinBarLabelAngel2=new QSpinBox(this); spinBarLabelAngel2->setPrefix(tr("rotation angel: ")); - spinBarLabelAngel2->setSuffix(QLatin1String("\xB0")); + spinBarLabelAngel2->setSuffix(QChar(0xB0)); spinBarLabelAngel2->setRange(-180,180); spinBarLabelAngel2->setValue(0); spinBarLabelAngel2->setSingleStep(15); diff --git a/lib/jkqtmathtext/CMakeLists.txt b/lib/jkqtmathtext/CMakeLists.txt index a44ad2c133..95d2bbef61 100644 --- a/lib/jkqtmathtext/CMakeLists.txt +++ b/lib/jkqtmathtext/CMakeLists.txt @@ -36,6 +36,7 @@ set(SOURCES ${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextsubsupernode.cpp ${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextsymbolnode.cpp ${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextnodetools.cpp + ${CMAKE_CURRENT_LIST_DIR}/nodes/jkqtmathtextwhitespacenode.cpp ) set(HEADERS @@ -69,6 +70,8 @@ set(HEADERS $ $ $ + $ + $ $ $ ) diff --git a/lib/jkqtmathtext/jkqtmathtext.cpp b/lib/jkqtmathtext/jkqtmathtext.cpp index b104c261e3..c42afe952a 100644 --- a/lib/jkqtmathtext/jkqtmathtext.cpp +++ b/lib/jkqtmathtext/jkqtmathtext.cpp @@ -33,6 +33,7 @@ #include "jkqtmathtext/nodes/jkqtmathtextsqrtnode.h" #include "jkqtmathtext/nodes/jkqtmathtextsubsupernode.h" #include "jkqtmathtext/nodes/jkqtmathtextsymbolnode.h" +#include "jkqtmathtext/nodes/jkqtmathtextwhitespacenode.h" #include "jkqtmathtext/nodes/jkqtmathtextnodetools.h" #include #include @@ -180,16 +181,21 @@ JKQTMathText::JKQTMathText(QObject* parent): addReplacementFont("blackboard", blackboardFont); } //qDebug()<<"add replacement fonts: "<(std::chrono::high_resolution_clock::now()-t0).count()/1000.0<<"ms"; t0=std::chrono::high_resolution_clock::now(); - setFontSans(sansFont, MTFEStandard); - setFontMathSans(sansFont, MTFEStandard); - setFontTypewriter(typewriterFont, MTFEStandard); - setFontRoman(serifFont, MTFEStandard); - setFontMathRoman(serifFont, MTFEStandard); - setFontCaligraphic(decorativeFont, MTFEStandard); - setFontBlackboard(blackboardFont, MTFEStandard); - setFontBlackboardSimulated(blackboardFont=="blackboard"); - setFontScript(scriptFont, MTFEStandard); - setFontFraktur(fracturFont, MTFEStandard); + setFontSans(sansFont, estimateJKQTMathTextFontEncoding(sansFont)); + setFontMathSans(sansFont, estimateJKQTMathTextFontEncoding(sansFont)); + setFontTypewriter(typewriterFont, estimateJKQTMathTextFontEncoding(typewriterFont)); + setFontRoman(serifFont, estimateJKQTMathTextFontEncoding(serifFont)); + setFontMathRoman(serifFont, estimateJKQTMathTextFontEncoding(serifFont)); + setFontCaligraphic(decorativeFont, estimateJKQTMathTextFontEncoding(decorativeFont)); + if (blackboardFont!="blackboard") { + setFontBlackboard(blackboardFont, estimateJKQTMathTextFontEncoding(blackboardFont)); + } else { + setFontBlackboardSimulated(blackboardFont=="blackboard"); + } + setFontScript(scriptFont, estimateJKQTMathTextFontEncoding(scriptFont)); + setFontFraktur(fracturFont, estimateJKQTMathTextFontEncoding(fracturFont)); + setFallbackFontGreek(symbolFont, estimateJKQTMathTextFontEncoding(symbolFont)); + setFallbackFontSymbols(symbolFont, estimateJKQTMathTextFontEncoding(symbolFont)); //qDebug()<<"set fonts: "<(std::chrono::high_resolution_clock::now()-t0).count()/1000.0<<"ms"; t0=std::chrono::high_resolution_clock::now(); useXITS(); //qDebug()<<"useXITS: "<(std::chrono::high_resolution_clock::now()-t0).count()/1000.0<<"ms"; t0=std::chrono::high_resolution_clock::now(); @@ -229,7 +235,7 @@ void JKQTMathText::loadSettings(const QSettings& settings, const QString& group) underbrace_factor=settings.value(group+"underbrace_factor", underbrace_factor).toDouble(); underbrace_bracesize_xfactor=settings.value(group+"underbrace_bracesize_xfactor", underbrace_bracesize_xfactor).toDouble(); underbrace_separation_xfactor=settings.value(group+"underbrace_separation_xfactor", underbrace_separation_xfactor).toDouble(); - underset_factor=settings.value(group+"undersetFactor", underset_factor).toDouble(); + underset_factor=settings.value(group+"underset_factor", underset_factor).toDouble(); brace_y_shift_factor=settings.value(group+"brace_y_shift_factor", brace_y_shift_factor).toDouble(); decoration_height_factor=settings.value(group+"decoration_height_factor", decoration_height_factor).toDouble(); decoration_separation_factor=settings.value(group+"decoration_separation_factor", decoration_separation_factor).toDouble(); @@ -243,6 +249,8 @@ void JKQTMathText::loadSettings(const QSettings& settings, const QString& group) sqrt_width_Xfactor=settings.value(group+"sqrt_width_Xfactor", sqrt_width_Xfactor).toDouble(); sqrt_height_factor=settings.value(group+"sqrt_height_factor", sqrt_height_factor).toDouble(); sqrt_smallfont_factor=settings.value(group+"sqrt_smallfont_factor", sqrt_smallfont_factor).toDouble(); + bigmathoperator_font_factor=settings.value(group+"bigmathoperator_font_factor", bigmathoperator_font_factor).toDouble(); + frac_nested_factor=settings.value(group+"frac_nested_factor", frac_nested_factor).toDouble(); if (settings.value(group+"use_stix_fonts", false).toBool()) useSTIX(); @@ -268,7 +276,7 @@ void JKQTMathText::saveSettings(QSettings& settings, const QString& group) const settings.setValue(group+ "underbrace_factor", underbrace_factor); settings.setValue(group+ "underbrace_bracesize_xfactor", underbrace_bracesize_xfactor); settings.setValue(group+ "underbrace_separation_xfactor", underbrace_separation_xfactor); - settings.setValue(group+ "undersetFactor", underset_factor); + settings.setValue(group+ "underset_factor", underset_factor); settings.setValue(group+ "operatorsubsuper_size_factor", operatorsubsuper_size_factor); settings.setValue(group+ "operatorsubsuper_distance_factor", operatorsubsuper_distance_factor); settings.setValue(group+ "operatorsubsuper_extraspace_factor", operatorsubsuper_extraspace_factor); @@ -282,22 +290,28 @@ void JKQTMathText::saveSettings(QSettings& settings, const QString& group) const settings.setValue(group+ "sqrt_width_Xfactor", sqrt_width_Xfactor); settings.setValue(group+ "sqrt_height_factor", sqrt_height_factor); settings.setValue(group+ "sqrt_smallfont_factor", sqrt_smallfont_factor); + settings.setValue(group+ "bigmathoperator_font_factor", bigmathoperator_font_factor); + settings.setValue(group+ "frac_nested_factor", frac_nested_factor); } bool JKQTMathText::useSTIX(bool mathModeOnly) { - const JKQTMathTextFontSpecifier xits=JKQTMathTextFontSpecifier::getSTIXFamilies(); + const JKQTMathTextFontSpecifier stixs=JKQTMathTextFontSpecifier::getSTIXFamilies(); bool res=false; - if (!mathModeOnly && !xits.fontName().isEmpty()) { - setFontRoman(xits.fontName(), MTFEunicode); + if (!mathModeOnly && !stixs.fontName().isEmpty()) { + setFontRoman(stixs.fontName(), MTFEUnicode); res=true; } - if (!xits.mathFontName().isEmpty()) { - setFontMathRoman(xits.mathFontName(), MTFEunicode); + if (!stixs.mathFontName().isEmpty()) { + setFontMathRoman(stixs.mathFontName(), MTFEUnicode); + setFallbackFontGreek(stixs.mathFontName(), MTFEUnicode); + setFallbackFontSymbols(stixs.mathFontName(), MTFEUnicode); res=true; - } else if (!xits.fontName().isEmpty()) { - setFontMathRoman(xits.fontName(), MTFEunicode); + } else if (!stixs.fontName().isEmpty()) { + setFontMathRoman(stixs.fontName(), MTFEUnicode); + setFallbackFontGreek(stixs.fontName(), MTFEUnicode); + setFallbackFontSymbols(stixs.fontName(), MTFEUnicode); res=true; } @@ -311,15 +325,15 @@ bool JKQTMathText::useXITS(bool mathModeOnly) bool res=false; if (!mathModeOnly && !xits.fontName().isEmpty()) { - setFontRoman(xits.fontName(), MTFEunicode); - setSymbolfontSymbol(xits.fontName(), MTFEunicode); - setSymbolfontGreek(xits.fontName(), MTFEunicode); + setFontRoman(xits.fontName(), MTFEUnicode); + setFallbackFontGreek(xits.fontName(), MTFEUnicode); + setFallbackFontSymbols(xits.fontName(), MTFEUnicode); res=true; } if (!xits.mathFontName().isEmpty()) { - setFontMathRoman(xits.mathFontName(), MTFEunicode); - setSymbolfontSymbol(xits.fontName(), MTFEunicode); - setSymbolfontGreek(xits.fontName(), MTFEunicode); + setFontMathRoman(xits.mathFontName(), MTFEUnicode); + setFallbackFontGreek(xits.mathFontName(), MTFEUnicode); + setFallbackFontSymbols(xits.mathFontName(), MTFEUnicode); res=true; } @@ -333,11 +347,15 @@ bool JKQTMathText::useASANA(bool mathModeOnly) bool res=false; if (!mathModeOnly && !asana.fontName().isEmpty()) { - setFontRoman(asana.fontName(), MTFEunicode); + setFontRoman(asana.fontName(), MTFEUnicode); + setFallbackFontGreek(asana.fontName(), MTFEUnicode); + setFallbackFontSymbols(asana.fontName(), MTFEUnicode); res=true; } if (!asana.mathFontName().isEmpty()) { - setFontMathRoman(asana.mathFontName(), MTFEunicode); + setFontMathRoman(asana.mathFontName(), MTFEUnicode); + setFallbackFontGreek(asana.mathFontName(), MTFEUnicode); + setFallbackFontSymbols(asana.mathFontName(), MTFEUnicode); res=true; } @@ -412,15 +430,13 @@ QPair JKQTMathText::getReplacementFont(const Q return res; } -QPair JKQTMathText::getFontData(JKQTMathTextEnvironmentFont font, bool in_math_environment, FontSubclass subclass) const +QPair JKQTMathText::getFontData(JKQTMathTextEnvironmentFont font, bool in_math_environment) 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); return QPair(fd.fontName, fd.fontEncoding); } @@ -533,52 +549,40 @@ JKQTMathTextFontEncoding JKQTMathText::getFontEncodingFraktur() const { return fontDefinitions[MTEfraktur].fontEncoding; } -void JKQTMathText::setSymbolfontGreek(JKQTMathTextEnvironmentFont font, const QString &__value, JKQTMathTextFontEncoding encoding) + +void JKQTMathText::setFallbackFontGreek(const QString &fontName, JKQTMathTextFontEncoding encoding) { - auto f=getReplacementFont(__value, __value, encoding); - fontDefinitions[font].symbolfontGreek = f.first; - fontDefinitions[font].symbolfontGreekEncoding = f.second; + auto f=getReplacementFont(fontName, fontName, encoding); + fontDefinitions[MTEFallbackGreek].fontName = f.first; + fontDefinitions[MTEFallbackGreek].fontEncoding = f.second; } -void JKQTMathText::setSymbolfontGreek(const QString &fontName, JKQTMathTextFontEncoding encoding) +void JKQTMathText::setFallbackFontSymbols(const QString &fontName, JKQTMathTextFontEncoding encoding) { - for (int f=0; f(MTenvironmentFontCount); f++) { - setSymbolfontGreek(static_cast(f), fontName, encoding); - } + auto f=getReplacementFont(fontName, fontName, encoding); + fontDefinitions[MTEFallbackSymbols].fontName = f.first; + fontDefinitions[MTEFallbackSymbols].fontEncoding = f.second; } -QString JKQTMathText::getSymbolfontGreek(JKQTMathTextEnvironmentFont font) const + +QString JKQTMathText::getFallbackFontGreek() const { - return fontDefinitions[font].symbolfontGreek; + return fontDefinitions[MTEFallbackGreek].fontName; } -JKQTMathTextFontEncoding JKQTMathText::getSymbolfontEncodingGreek(JKQTMathTextEnvironmentFont font) const +QString JKQTMathText::getFallbackFontSymbols() const { - return fontDefinitions[font].symbolfontGreekEncoding; + return fontDefinitions[MTEFallbackSymbols].fontName; } -void JKQTMathText::setSymbolfontSymbol(JKQTMathTextEnvironmentFont font, const QString &__value, JKQTMathTextFontEncoding encoding) +JKQTMathTextFontEncoding JKQTMathText::getFontEncodingFallbackFontGreek() const { - auto f=getReplacementFont(__value, __value, encoding); - fontDefinitions[font].symbolfontSymbol = f.first; - fontDefinitions[font].symbolfontSymbolEncoding = f.second; + return fontDefinitions[MTEFallbackGreek].fontEncoding; } -void JKQTMathText::setSymbolfontSymbol(const QString &fontName, JKQTMathTextFontEncoding encoding) +JKQTMathTextFontEncoding JKQTMathText::getFontEncodingFallbackFontSymbols() const { - for (int f=0; f(MTenvironmentFontCount); f++) { - setSymbolfontSymbol(static_cast(f), fontName, encoding); - } -} - -QString JKQTMathText::getSymbolfontSymbol(JKQTMathTextEnvironmentFont font) const -{ - return fontDefinitions[font].symbolfontSymbol; -} - -JKQTMathTextFontEncoding JKQTMathText::getSymbolfontEncodingSymbol(JKQTMathTextEnvironmentFont font) const -{ - return fontDefinitions[font].symbolfontSymbolEncoding; + return fontDefinitions[MTEFallbackSymbols].fontEncoding; } void JKQTMathText::setFontCaligraphic(const QString &__value, JKQTMathTextFontEncoding encoding) @@ -1138,12 +1142,12 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType while (currentToken!=MTTnone) { getNew=true; if (currentToken==MTTtext) { - QString text=currentTokenName; - bool addWhite=(getToken()==MTTwhitespace) && (!parsingMathEnvironment); + const QString text=currentTokenName; + const bool addWhite=(getToken()==MTTwhitespace) && (!parsingMathEnvironment); getNew=addWhite; if (parsingMathEnvironment) { - if (mathEnvironmentSpecialText.contains(text.trimmed())) { - nl->addChild(new JKQTMathTextSymbolNode(this, text, addWhite)); + if (mathEnvironmentSpecialText.contains(text.trimmed()) && JKQTMathTextSymbolNode::hasSymbol(text.trimmed())) { + nl->addChild(new JKQTMathTextSymbolNode(this, text.trimmed(), addWhite)); } else { nl->addChild(new JKQTMathTextTextNode(this, text, addWhite, parsingMathEnvironment)); } @@ -1153,321 +1157,330 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType } else if (currentToken==MTTinstruction) { const QString currentInstructionName=currentTokenName; if (currentInstructionName=="\\") break; // break on linebrak character - getToken(); // look at next token - if (currentToken==MTTopenbrace) { - //std::cout<<"found '{' after '"<addChild(new JKQTMathTextSqrtNode(this, parseLatexString(true))); - } else if (currentInstructionName=="cbrt") { - nl->addChild(new JKQTMathTextSqrtNode(this, parseLatexString(true), new JKQTMathTextTextNode(this, "3", false))); - } else if (currentInstructionName=="verb") { - QString text=""; - currentTokenID++; - if (currentTokenID<=parseString.size()-1) { - QChar c=parseString[currentTokenID]; - while (c!='}' && (currentTokenIDaddChild(new JKQTMathTextTextNode(this, text, false)); - } - } else if (currentInstructionName=="frac") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMfrac)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="dfrac" || currentInstructionName=="cfrac") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMdfrac)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="sfrac" || currentInstructionName=="slantfrac" || currentInstructionName=="xfrac") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMsfrac)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="stfrac" || currentInstructionName=="nicefrac" || currentInstructionName=="slanttextfrac" || currentInstructionName=="xtfrac") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMstfrac)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="tfrac") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMtfrac)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="stackrel") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMstackrel)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="binom") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextBraceNode(this, MTBTParenthesis, MTBTParenthesis, new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMstackrel))); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="underbrace") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMunderbrace)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="underbracket") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMunderbracket)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="underset") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMunderset)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="overbrace") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMoverbrace)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="overbracket") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMoverbracket)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="overset") { - JKQTMathTextNode* n1=parseLatexString(true); - JKQTMathTextNode* n2=nullptr; - if (getToken()==MTTopenbrace) n2=parseLatexString(true); - if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMoverset)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else if (currentInstructionName=="begin") { - if (getToken()==MTTtext) { - QString envname=currentTokenName; - while (currentToken!=MTTclosebrace) getToken(); // find closing brace '}' after '\\begin{name' - if (envname=="matrix" || envname=="array" || envname=="aligned" || envname=="align" || envname=="cases" || envname=="pmatrix"|| envname=="bmatrix"|| envname=="Bmatrix"|| envname=="vmatrix"|| envname=="Vmatrix") { - QVector< QVector > items; - //int lines=0; - //int cols=0; - bool first=true; - QVector line; - //std::cout<<"found \\begin{matrix}\n"; - while (first || currentToken==MTTampersand || (currentToken==MTTinstruction && currentTokenName=="\\")) { - JKQTMathTextNode* it=parseLatexString(true, MTBTAny, envname); - if (currentToken==MTTampersand) { - //std::cout<<" appending item\n"; - line.append(it); - } else { - line.append(it); - //std::cout<<" appending item and line with "<addChild(new JKQTMathTextBraceNode(this, MTBTParenthesis, MTBTParenthesis, new JKQTMathTextMatrixNode(this, items))); - else if (envname=="cases") nl->addChild(new JKQTMathTextBraceNode(this, MTBTCurlyBracket, MTBTNone, new JKQTMathTextMatrixNode(this, items))); - else if (envname=="bmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTSquareBracket, MTBTSquareBracket, new JKQTMathTextMatrixNode(this, items))); - else if (envname=="Bmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTCurlyBracket, MTBTCurlyBracket, new JKQTMathTextMatrixNode(this, items))); - else if (envname=="vmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTSingleLine, MTBTSingleLine, new JKQTMathTextMatrixNode(this, items))); - else if (envname=="Vmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTDoubleLine, MTBTDoubleLine, new JKQTMathTextMatrixNode(this, items))); - else nl->addChild(new JKQTMathTextMatrixNode(this, items)); - //std::cout<<" creating matrix-node ... done!\n"; - } else { - error_list.append(tr("error @ ch. %1: unknown environment '%2'").arg(currentTokenID).arg(envname)); - } - } else { // find next '}' - error_list.append(tr("error @ ch. %1: text after '\\begin{' expected!").arg(currentTokenID)); - while (currentToken!=MTTclosebrace) getToken(); - getNew=true; - } - } else if (currentInstructionName=="end") { - if (getToken()==MTTtext) { - QString envname=currentTokenName; - while (currentToken!=MTTclosebrace) getToken(); // find closing brace '}' after '\\begin{name' - if (envname==quitOnEnvironmentEnd) { - break; - } else { - error_list.append(tr("error @ ch. %1: '\\end{%2}' widthout preceding '\\begin{%3}'").arg(currentTokenID).arg(envname).arg(envname)); - } - } else { // find next '}' - error_list.append(tr("error @ ch. %1: text after '\\begin{' expected!").arg(currentTokenID)); - while (currentToken!=MTTclosebrace) getToken(); - getNew=true; - } - } else if (currentInstructionName=="vec") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDvec, parseLatexString(true))); - } else if (currentInstructionName=="overline"||currentInstructionName=="oline"||currentInstructionName=="ol") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDoverline, parseLatexString(true))); - } else if (currentInstructionName=="underline"||currentInstructionName=="uline"||currentInstructionName=="ul") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDunderline, parseLatexString(true))); - } else if (currentInstructionName=="uuline"||currentInstructionName=="uul") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDdoubleunderline, parseLatexString(true))); - } else if (currentInstructionName=="ooline"||currentInstructionName=="ool") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDdoubleoverline, parseLatexString(true))); - } else if (currentInstructionName=="arrow"||currentInstructionName=="overrightarrow"||currentInstructionName=="overarrow") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDarrow, parseLatexString(true))); - } else if (currentInstructionName=="hat" || currentInstructionName=="^") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDhat, parseLatexString(true))); - } else if (currentInstructionName=="widehat") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDwidehat, parseLatexString(true))); - } else if (currentInstructionName=="check" || currentInstructionName=="v") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDcheck, parseLatexString(true))); - } else if (currentInstructionName=="widecheck") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDwidecheck, parseLatexString(true))); - } else if (currentInstructionName=="bar") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDbar, parseLatexString(true))); - } else if (currentInstructionName=="dot" || currentInstructionName==".") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDdot, parseLatexString(true))); - } else if (currentInstructionName=="ocirc") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDocirc, parseLatexString(true))); - } else if (currentInstructionName=="tilde" || currentInstructionName=="~") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDtilde, parseLatexString(true))); - } else if (currentInstructionName=="breve" || currentInstructionName=="u") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDbreve, parseLatexString(true))); - } else if (currentInstructionName=="widetilde") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDwidetilde, parseLatexString(true))); - } else if (currentInstructionName=="ddot") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDddot, parseLatexString(true))); - } else if (currentInstructionName=="cancel") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDcancel, parseLatexString(true))); - } else if (currentInstructionName=="xcancel") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDxcancel, parseLatexString(true))); - } else if (currentInstructionName=="bcancel") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDbcancel, parseLatexString(true))); - } else if (currentInstructionName=="strike" || currentInstructionName=="st" || currentInstructionName=="sout") { - nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDstrike, parseLatexString(true))); - } else { - if (currentInstructionName=="textcolor" || currentInstructionName=="mathcolor" || currentInstructionName=="color" || currentInstructionName=="colorbox") { - bool foundError=true; - QString col=""; - if (getToken()==MTTtext) { - col=currentTokenName; - if (getToken()==MTTclosebrace) { - if (getToken()==MTTopenbrace) { - foundError=false; - } - } - } - if (foundError) error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - else nl->addChild(new JKQTMathTextInstruction1Node(this, currentInstructionName, parseLatexString(true), QStringList(col))); - - - } else { - nl->addChild(new JKQTMathTextInstruction1Node(this, currentInstructionName, parseLatexString(true))); - } - } - if (getNew) getToken(); - if (currentToken==MTTinstruction && currentTokenName=="limits") { - if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(true); - getNew=true; - } else if (currentToken==MTTinstruction && currentTokenName=="nolimits") { - if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(false); - getNew=true; - } else { - getNew=false; - } - - } else if (currentToken==MTTopenbracket && currentInstructionName!="left") { - //std::cout<<"found '[' after '"<addChild(new JKQTMathTextSqrtNode(this, n2, n1)); - else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); - } else { - nl->addChild(new JKQTMathTextTextNode(this, "[", false)); - } + if (JKQTMathTextWhitespaceNode::supportsInstructionName(currentInstructionName)) { + nl->addChild(new JKQTMathTextWhitespaceNode(currentInstructionName, this)); + } else if (JKQTMathTextSymbolNode::hasSymbol(currentInstructionName)) { + nl->addChild(new JKQTMathTextSymbolNode(this, currentInstructionName, false)); } else { - bool subSuperscriptAboveBelowNode=false; - //std::cout<<"did not find '{' after '"<0) { - bool tokenWasNoBrace=false; - const QString firstTokenChar(currentTokenName[0]); - if (TokenNameMatchesJKQTMathTextBraceType(firstTokenChar, quitOnClosingBrace, true, &tokenWasNoBrace)) { - if (quitOnClosingBrace!=MTBTAny) currentTokenName=currentTokenName.right(currentTokenName.size()-1); + getToken(); // look at next token + if (currentToken==MTTopenbrace) { + //std::cout<<"found '{' after '"<addChild(new JKQTMathTextSqrtNode(this, parseLatexString(true))); + } else if (currentInstructionName=="cbrt") { + nl->addChild(new JKQTMathTextSqrtNode(this, parseLatexString(true), new JKQTMathTextTextNode(this, "3", false))); + } else if (currentInstructionName=="verb") { + QString text=""; + currentTokenID++; + if (currentTokenID<=parseString.size()-1) { + QChar c=parseString[currentTokenID]; + while (c!='}' && (currentTokenIDaddChild(new JKQTMathTextTextNode(this, text, false)); + } + } else if (currentInstructionName=="frac") { + JKQTMathTextNode* n1=parseLatexString(true); + JKQTMathTextNode* n2=nullptr; + if (getToken()==MTTopenbrace) n2=parseLatexString(true); + if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMfrac)); + else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); + } else if (currentInstructionName=="dfrac" || currentInstructionName=="cfrac") { + JKQTMathTextNode* n1=parseLatexString(true); + JKQTMathTextNode* n2=nullptr; + if (getToken()==MTTopenbrace) n2=parseLatexString(true); + if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMdfrac)); + else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); + } else if (currentInstructionName=="sfrac" || currentInstructionName=="slantfrac" || currentInstructionName=="xfrac") { + JKQTMathTextNode* n1=parseLatexString(true); + JKQTMathTextNode* n2=nullptr; + if (getToken()==MTTopenbrace) n2=parseLatexString(true); + if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMsfrac)); + else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); + } else if (currentInstructionName=="stfrac" || currentInstructionName=="nicefrac" || currentInstructionName=="slanttextfrac" || currentInstructionName=="xtfrac") { + JKQTMathTextNode* n1=parseLatexString(true); + JKQTMathTextNode* n2=nullptr; + if (getToken()==MTTopenbrace) n2=parseLatexString(true); + if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMstfrac)); + else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); + } else if (currentInstructionName=="tfrac") { + JKQTMathTextNode* n1=parseLatexString(true); + JKQTMathTextNode* n2=nullptr; + if (getToken()==MTTopenbrace) n2=parseLatexString(true); + if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMtfrac)); + else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); + } else if (currentInstructionName=="stackrel") { + JKQTMathTextNode* n1=parseLatexString(true); + JKQTMathTextNode* n2=nullptr; + if (getToken()==MTTopenbrace) n2=parseLatexString(true); + if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMstackrel)); + else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); + } else if (currentInstructionName=="binom") { + JKQTMathTextNode* n1=parseLatexString(true); + JKQTMathTextNode* n2=nullptr; + if (getToken()==MTTopenbrace) n2=parseLatexString(true); + if (n1 && n2) nl->addChild(new JKQTMathTextBraceNode(this, MTBTParenthesis, MTBTParenthesis, new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMstackrel))); + else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); + } else if (currentInstructionName=="underbrace") { + JKQTMathTextNode* n1=parseLatexString(true); + JKQTMathTextNode* n2=nullptr; + if (getToken()==MTTopenbrace) n2=parseLatexString(true); + if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMunderbrace)); + else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); + } else if (currentInstructionName=="underbracket") { + JKQTMathTextNode* n1=parseLatexString(true); + JKQTMathTextNode* n2=nullptr; + if (getToken()==MTTopenbrace) n2=parseLatexString(true); + if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMunderbracket)); + else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); + } else if (currentInstructionName=="underset") { + JKQTMathTextNode* n1=parseLatexString(true); + JKQTMathTextNode* n2=nullptr; + if (getToken()==MTTopenbrace) n2=parseLatexString(true); + if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMunderset)); + else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); + } else if (currentInstructionName=="overbrace") { + JKQTMathTextNode* n1=parseLatexString(true); + JKQTMathTextNode* n2=nullptr; + if (getToken()==MTTopenbrace) n2=parseLatexString(true); + if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMoverbrace)); + else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); + } else if (currentInstructionName=="overbracket") { + JKQTMathTextNode* n1=parseLatexString(true); + JKQTMathTextNode* n2=nullptr; + if (getToken()==MTTopenbrace) n2=parseLatexString(true); + if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMoverbracket)); + else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); + } else if (currentInstructionName=="overset") { + JKQTMathTextNode* n1=parseLatexString(true); + JKQTMathTextNode* n2=nullptr; + if (getToken()==MTTopenbrace) n2=parseLatexString(true); + if (n1 && n2) nl->addChild(new JKQTMathTextFracNode(this, n1, n2, JKQTMathTextFracNode::MTFMoverset)); + else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); + } else if (currentInstructionName=="begin") { + if (getToken()==MTTtext) { + QString envname=currentTokenName; + while (currentToken!=MTTclosebrace) getToken(); // find closing brace '}' after '\\begin{name' + if (envname=="matrix" || envname=="array" || envname=="aligned" || envname=="align" || envname=="cases" || envname=="pmatrix"|| envname=="bmatrix"|| envname=="Bmatrix"|| envname=="vmatrix"|| envname=="Vmatrix") { + QVector< QVector > items; + //int lines=0; + //int cols=0; + bool first=true; + QVector line; + //std::cout<<"found \\begin{matrix}\n"; + while (first || currentToken==MTTampersand || (currentToken==MTTinstruction && currentTokenName=="\\")) { + JKQTMathTextNode* it=parseLatexString(true, MTBTAny, envname); + if (currentToken==MTTampersand) { + //std::cout<<" appending item\n"; + line.append(it); + } else { + line.append(it); + //std::cout<<" appending item and line with "<addChild(new JKQTMathTextBraceNode(this, MTBTParenthesis, MTBTParenthesis, new JKQTMathTextMatrixNode(this, items))); + else if (envname=="cases") nl->addChild(new JKQTMathTextBraceNode(this, MTBTCurlyBracket, MTBTNone, new JKQTMathTextMatrixNode(this, items))); + else if (envname=="bmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTSquareBracket, MTBTSquareBracket, new JKQTMathTextMatrixNode(this, items))); + else if (envname=="Bmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTCurlyBracket, MTBTCurlyBracket, new JKQTMathTextMatrixNode(this, items))); + else if (envname=="vmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTSingleLine, MTBTSingleLine, new JKQTMathTextMatrixNode(this, items))); + else if (envname=="Vmatrix") nl->addChild(new JKQTMathTextBraceNode(this, MTBTDoubleLine, MTBTDoubleLine, new JKQTMathTextMatrixNode(this, items))); + else nl->addChild(new JKQTMathTextMatrixNode(this, items)); + //std::cout<<" creating matrix-node ... done!\n"; + } else { + error_list.append(tr("error @ ch. %1: unknown environment '%2'").arg(currentTokenID).arg(envname)); + } + } else { // find next '}' + error_list.append(tr("error @ ch. %1: text after '\\begin{' expected!").arg(currentTokenID)); + while (currentToken!=MTTclosebrace) getToken(); + getNew=true; + } + } else if (currentInstructionName=="end") { + if (getToken()==MTTtext) { + QString envname=currentTokenName; + while (currentToken!=MTTclosebrace) getToken(); // find closing brace '}' after '\\begin{name' + if (envname==quitOnEnvironmentEnd) { break; } else { - getNew=false; + error_list.append(tr("error @ ch. %1: '\\end{%2}' widthout preceding '\\begin{%3}'").arg(currentTokenID).arg(envname).arg(envname)); } + } else { // find next '}' + error_list.append(tr("error @ ch. %1: text after '\\begin{' expected!").arg(currentTokenID)); + while (currentToken!=MTTclosebrace) getToken(); + getNew=true; } - } else if (currentToken==MTTinstruction) { - if (InstructionNameMatchesJKQTMathTextBraceType(currentTokenName, quitOnClosingBrace, true)) { - currentTokenName=currentTokenName.right(currentTokenName.size()-1); - break; - } - } else if (currentToken==MTTclosebracket) { - if (quitOnClosingBrace==MTBTSquareBracket || quitOnClosingBrace==MTBTAny) { - currentTokenName=currentTokenName.right(currentTokenName.size()-1); - break; - } + } else if (currentInstructionName=="vec") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDvec, parseLatexString(true))); + } else if (currentInstructionName=="overline"||currentInstructionName=="oline"||currentInstructionName=="ol") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDoverline, parseLatexString(true))); + } else if (currentInstructionName=="underline"||currentInstructionName=="uline"||currentInstructionName=="ul") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDunderline, parseLatexString(true))); + } else if (currentInstructionName=="uuline"||currentInstructionName=="uul") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDdoubleunderline, parseLatexString(true))); + } else if (currentInstructionName=="ooline"||currentInstructionName=="ool") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDdoubleoverline, parseLatexString(true))); + } else if (currentInstructionName=="arrow"||currentInstructionName=="overrightarrow"||currentInstructionName=="overarrow") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDarrow, parseLatexString(true))); + } else if (currentInstructionName=="hat" || currentInstructionName=="^") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDhat, parseLatexString(true))); + } else if (currentInstructionName=="widehat") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDwidehat, parseLatexString(true))); + } else if (currentInstructionName=="check" || currentInstructionName=="v") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDcheck, parseLatexString(true))); + } else if (currentInstructionName=="widecheck") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDwidecheck, parseLatexString(true))); + } else if (currentInstructionName=="bar") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDbar, parseLatexString(true))); + } else if (currentInstructionName=="dot" || currentInstructionName==".") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDdot, parseLatexString(true))); + } else if (currentInstructionName=="ocirc") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDocirc, parseLatexString(true))); + } else if (currentInstructionName=="tilde" || currentInstructionName=="~") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDtilde, parseLatexString(true))); + } else if (currentInstructionName=="breve" || currentInstructionName=="u") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDbreve, parseLatexString(true))); + } else if (currentInstructionName=="widetilde") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDwidetilde, parseLatexString(true))); + } else if (currentInstructionName=="ddot") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDddot, parseLatexString(true))); + } else if (currentInstructionName=="cancel") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDcancel, parseLatexString(true))); + } else if (currentInstructionName=="xcancel") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDxcancel, parseLatexString(true))); + } else if (currentInstructionName=="bcancel") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDbcancel, parseLatexString(true))); + } else if (currentInstructionName=="strike" || currentInstructionName=="st" || currentInstructionName=="sout") { + nl->addChild(new JKQTMathTextDecoratedNode(this, JKQTMathTextDecoratedNode::MTDstrike, parseLatexString(true))); } else { - getNew=false; - } - } else if (currentInstructionName=="left") { - if (currentToken==MTTtext) { - if (currentTokenName.size()>0) { - const QString firstTokenChar(currentTokenName[0]); - const JKQTMathTextBraceType bracetype=TokenName2JKQTMathTextBraceType(firstTokenChar); - if (bracetype==MTBTNone) { - currentTokenName=currentTokenName.right(currentTokenName.size()-1); - JKQTMathTextNode* cn=parseLatexString(currentTokenName.size()<=0, MTBTAny); - nl->addChild(new JKQTMathTextBraceNode(this, MTBTNone, bracetype, cn)); - } else if (isPrintableJKQTMathTextBraceType(bracetype)) { - currentTokenName=currentTokenName.right(currentTokenName.size()-1); // we already used the first character from the text token! - nl->addChild(new JKQTMathTextBraceNode(this, bracetype, bracetype, parseLatexString(currentTokenName.size()<=0, bracetype))); - } else { - getNew=false; + if (currentInstructionName=="textcolor" || currentInstructionName=="mathcolor" || currentInstructionName=="color" || currentInstructionName=="colorbox") { + bool foundError=true; + QString col=""; + if (getToken()==MTTtext) { + col=currentTokenName; + if (getToken()==MTTclosebrace) { + if (getToken()==MTTopenbrace) { + foundError=false; + } + } } - } - } else if (currentToken==MTTinstruction) { - const JKQTMathTextBraceType bracetypeopening=InstructionName2OpeningJKQTMathTextBraceType(currentTokenName); - if (bracetypeopening!=MTBTUnknown) { - nl->addChild(new JKQTMathTextBraceNode(this, bracetypeopening, bracetypeopening, parseLatexString(true, bracetypeopening))); - } else if (currentToken==MTTinstruction && TokenNameMatchesJKQTMathTextBraceType(currentTokenName, quitOnClosingBrace, true)) { - break; - } - } else if (currentToken==MTTopenbracket) { - nl->addChild(new JKQTMathTextBraceNode(this, MTBTSquareBracket, MTBTSquareBracket, parseLatexString(true, MTBTSquareBracket))); - } else { - error_list.append(tr("error @ ch. %1: unexpected token after \\left").arg(currentTokenID)); - } + if (foundError) error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); + else nl->addChild(new JKQTMathTextInstruction1Node(this, currentInstructionName, parseLatexString(true), QStringList(col))); - } else { - nl->addChild(new JKQTMathTextSymbolNode(this, currentInstructionName, false)); - static QSet subsupOperations= (QSet()<<"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"); - if (subsupOperations.contains(currentInstructionName) && parsingMathEnvironment) { - nl->getLastChild()->setSubSuperscriptAboveBelowNode(true); + } else { + nl->addChild(new JKQTMathTextInstruction1Node(this, currentInstructionName, parseLatexString(true))); + } } + if (getNew) getToken(); if (currentToken==MTTinstruction && currentTokenName=="limits") { if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(true); + getNew=true; } else if (currentToken==MTTinstruction && currentTokenName=="nolimits") { if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(false); + getNew=true; } else { getNew=false; } + } else if (currentToken==MTTopenbracket && currentInstructionName!="left") { + //std::cout<<"found '[' after '"<addChild(new JKQTMathTextSqrtNode(this, n2, n1)); + else error_list.append(tr("error @ ch. %1: expected two arguments in '{' braces after '%2' command").arg(currentTokenID).arg(currentInstructionName)); + } else { + nl->addChild(new JKQTMathTextTextNode(this, "[", false)); + } + } else { + bool subSuperscriptAboveBelowNode=false; + //std::cout<<"did not find '{' after '"<0) { + bool tokenWasNoBrace=false; + const QString firstTokenChar(currentTokenName[0]); + if (TokenNameMatchesJKQTMathTextBraceType(firstTokenChar, quitOnClosingBrace, true, &tokenWasNoBrace)) { + if (quitOnClosingBrace!=MTBTAny) currentTokenName=currentTokenName.right(currentTokenName.size()-1); + break; + } else { + getNew=false; + } + } + } else if (currentToken==MTTinstruction) { + if (InstructionNameMatchesJKQTMathTextBraceType(currentTokenName, quitOnClosingBrace, true)) { + currentTokenName=currentTokenName.right(currentTokenName.size()-1); + break; + } + } else if (currentToken==MTTclosebracket) { + if (quitOnClosingBrace==MTBTSquareBracket || quitOnClosingBrace==MTBTAny) { + currentTokenName=currentTokenName.right(currentTokenName.size()-1); + break; + } + } else { + getNew=false; + } + } else if (currentInstructionName=="left") { + if (currentToken==MTTtext) { + if (currentTokenName.size()>0) { + const QString firstTokenChar(currentTokenName[0]); + const JKQTMathTextBraceType bracetype=TokenName2JKQTMathTextBraceType(firstTokenChar); + if (bracetype==MTBTNone) { + currentTokenName=currentTokenName.right(currentTokenName.size()-1); + JKQTMathTextNode* cn=parseLatexString(currentTokenName.size()<=0, MTBTAny); + nl->addChild(new JKQTMathTextBraceNode(this, MTBTNone, bracetype, cn)); + } else if (isPrintableJKQTMathTextBraceType(bracetype)) { + currentTokenName=currentTokenName.right(currentTokenName.size()-1); // we already used the first character from the text token! + nl->addChild(new JKQTMathTextBraceNode(this, bracetype, bracetype, parseLatexString(currentTokenName.size()<=0, bracetype))); + } else { + getNew=false; + } + } + } else if (currentToken==MTTinstruction) { + const JKQTMathTextBraceType bracetypeopening=InstructionName2OpeningJKQTMathTextBraceType(currentTokenName); + if (bracetypeopening!=MTBTUnknown) { + nl->addChild(new JKQTMathTextBraceNode(this, bracetypeopening, bracetypeopening, parseLatexString(true, bracetypeopening))); + } else if (currentToken==MTTinstruction && TokenNameMatchesJKQTMathTextBraceType(currentTokenName, quitOnClosingBrace, true)) { + break; + } + } else if (currentToken==MTTopenbracket) { + nl->addChild(new JKQTMathTextBraceNode(this, MTBTSquareBracket, MTBTSquareBracket, parseLatexString(true, MTBTSquareBracket))); + } else { + error_list.append(tr("error @ ch. %1: unexpected token after \\left").arg(currentTokenID)); + } + + } else if (JKQTMathTextWhitespaceNode::supportsInstructionName(currentInstructionName)) { + nl->addChild(new JKQTMathTextWhitespaceNode(currentInstructionName, this)); + } else if (JKQTMathTextSymbolNode::hasSymbol(currentInstructionName)) { + nl->addChild(new JKQTMathTextSymbolNode(this, currentInstructionName, false)); + static QSet subsupOperations= (QSet()<<"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"); + if (subsupOperations.contains(currentInstructionName) && parsingMathEnvironment) { + nl->getLastChild()->setSubSuperscriptAboveBelowNode(true); + } + if (currentToken==MTTinstruction && currentTokenName=="limits") { + if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(true); + } else if (currentToken==MTTinstruction && currentTokenName=="nolimits") { + if (nl->hasChildren()) nl->getLastChild()->setSubSuperscriptAboveBelowNode(false); + } else { + getNew=false; + } + + } else { + error_list.append(tr("error @ ch. %1: unknown instruction \\%2").arg(currentTokenID).arg(currentInstructionName)); + } } } } else if (currentToken==MTTwhitespace) { @@ -1481,12 +1494,14 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType getToken(); // look at next token if (currentToken==MTTopenbrace) { child=new JKQTMathTextInstruction1Node(this, name, parseLatexString(true)); - } else { - //bool addWhite=(currentToken==MTTwhitespace); - //getNew=addWhite; - //child=new JKQTMathTextSymbolNode(this, name, addWhite); + } else if (JKQTMathTextWhitespaceNode::supportsInstructionName(name)) { + getNew=false; + child=new JKQTMathTextWhitespaceNode(name, this); + } else if (JKQTMathTextSymbolNode::hasSymbol(name)) { getNew=false; child=new JKQTMathTextSymbolNode(this, name, false); + } else { + error_list.append(tr("error @ ch. %1: unknown instruction \\%2").arg(currentTokenID).arg(name)); } } else if (currentToken==MTTopenbrace) { child=parseLatexString(true); @@ -1507,16 +1522,20 @@ JKQTMathTextNode* JKQTMathText::parseLatexString(bool get, JKQTMathTextBraceType JKQTMathTextNode* child=nullptr; JKQTMathTextNode* child2=nullptr; if (currentToken==MTTinstruction) { - QString name=currentTokenName; - getToken(); // look at next token - if (currentToken==MTTopenbrace) { - child=new JKQTMathTextInstruction1Node(this, name, parseLatexString(true)); + const QString currentInstructionName=currentTokenName; + if (JKQTMathTextWhitespaceNode::supportsInstructionName(currentInstructionName)) { + getNew=true; + nl->addChild(new JKQTMathTextWhitespaceNode(currentInstructionName, this)); + } else if (JKQTMathTextSymbolNode::hasSymbol(currentInstructionName)){ + getNew=true; + child=new JKQTMathTextSymbolNode(this, currentInstructionName, false); } else { - //bool addWhite=(currentToken==MTTwhitespace); - //getNew=addWhite; - //child=new JKQTMathTextSymbolNode(this, name, addWhite); - getNew=false; - child=new JKQTMathTextSymbolNode(this, name, false); + getToken(); // look at next token + if (currentToken==MTTopenbrace) { + child=new JKQTMathTextInstruction1Node(this, currentInstructionName, parseLatexString(true)); + } else { + error_list.append(tr("error @ ch. %1: unknown instruction \\%2").arg(currentTokenID).arg(currentInstructionName)); + } } } else if (currentToken==MTTopenbrace) { child=parseLatexString(true); diff --git a/lib/jkqtmathtext/jkqtmathtext.h b/lib/jkqtmathtext/jkqtmathtext.h index 4b0fea112e..235cbb0508 100644 --- a/lib/jkqtmathtext/jkqtmathtext.h +++ b/lib/jkqtmathtext/jkqtmathtext.h @@ -186,18 +186,19 @@ class JKQTMathTextNode; // forward \section JKQTMathTextSuppoertedFonts Font Handling Several fonts are defined as properties to the class: - - A "roman" font used as the standard font ( setFontRoman() ) - - A "sans-serif" font which may be activated with \c \\sf ... ( setFontSans() ) - - A "typewriter" font which may be activated with \c \\tt ... ( setFontTypewriter() ) - - A "script" font which may be activated with \c \\script ... ( setFontScript() ) - - A greek font which is used to display greek letters \c \\alpha ... ( setSymbolfontGreek() ) - - A symbol font used to display special (math) symbols. ( setSymbolfontSymbol() ) - - A "roman" font used as the standard font in math mode ( setFontMathRoman() ) - - A "sans-serif" used as sans serif font in math mode ( setFontMathSans() ) - - A "blackboard" font used to display double stroked characters ( setFontBlackboard() ) - - A "caligraphic" font used to display caligraphic characters ( setFontCaligraphic() ) + - A "roman" (MTEroman / MTEmathRoman) font used as the standard font ( setFontRoman() and for use in math mode setFontMathRoman() ) + - A "sans-serif" (MTEsans / MTEmathSans) font which may be activated with \c \\sf ... ( setFontSans() and for use in math mode setFontMathSans() ) + - A "typewriter" (MTEtypewriter) font which may be activated with \c \\tt ... ( setFontTypewriter() ) + - A "script" (MTEscript) font which may be activated with \c \\script ... ( setFontScript() ) + - A "math-roman" (MTEmathRoman) font used as the standard font in math mode ( setFontMathRoman() ) + - A "math-sans-serif" (MTEmathSans) used as sans serif font in math mode ( setFontMathSans() ) + - A "blackboard" (MTEblackboard) font used to display double stroked characters ( setFontBlackboard() ) + - A "caligraphic" (MTEcaligraphic) font used to display caligraphic characters ( setFontCaligraphic() ) + - A "fraktur" (MTEfraktur) font used to display fraktur characters ( setFontFraktur() ) + - A fallback font MTEFallbackGreek for greek letter (if the letters are not present in the currently used font) \c \\alpha ... ( setFallbackFontGreek() ) + - A fallback font MTEFallbackSymbols for (math) symbols (if the symbols are not present in the currently used font). ( setFallbackFontSymbols() ) . - + These fonts are generic font classes, which font is actually used can be configured in JKQTMathText class with the \c set...() functions mentioned above. You can also use these functions to set the fonts used for math rendering in math-mode: - useSTIX() use the STIX fonts from https://www.stixfonts.org/ in math-mode
    \image html jkqtmathtext/jkqtmathparser_stix.png - useXITS() use the XITS fonts from https://github.com/alif-type/xits in math-mode. These are included by default in this library and also activated by default.
    \image html jkqtmathtext/jkqtmathparser_xits.png @@ -208,11 +209,16 @@ class JKQTMathTextNode; // forward
    using "Comic Sans MS": \image html jkqtmathtext/jkqtmathparser_comicsans.png . - Math-mode is activated by enclosing your equation in \c $...$ or \c \\[...\\] . This mode is optimized for mathematical equations. Here is an example of the difference: - - math-mode (XITS fonts are used, whitespaces are mostly not drawn directly, symbol spacing is different) \c $...$:
    \image html jkqtmathtext/schreq_mathmode.png - - normal mode (Times new Roman is used, whitespaces are evaluated directly):
    \image html jkqtmathtext/schreq_normalmode.png + - math-mode (MTEmathRoman and MTEmathSans, whitespaces are mostly not drawn directly, symbol spacing is different) \c $...$:
    \image html jkqtmathtext/schreq_mathmode.png + - normal mode (MTEroman and MTEsans is used, whitespaces are evaluated directly):
    \image html jkqtmathtext/schreq_normalmode.png . + + Font Lookup for symbols works as follows in JKQTMathTextSymbolNode: + - if a character is found in the current (or to be used) font, it is taken from there + - if the character is not found, it is looked for in the fallback fonts MTEFallbackGreek and MTEFallbackSymbols + - as a last resort, some symbols can be created otherwise, so if neither of the two options above + contain the required symbol, the symbol might be synthesized otherwise, or a rectangle with the size of "X" is drawn instead \section JKQTMathTextToHTML Convert to HTML @@ -291,16 +297,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject { /** \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 getReplacementFont(const QString &nonUseFont, const QString &defaultFont, JKQTMathTextFontEncoding defaultFontEncoding) const; - /** \brief font subclasses, used by getFontData() */ - enum class FontSubclass { - Text, - Default=Text, - Symbols, - Greek, - }; - /** \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 getFontData(JKQTMathTextEnvironmentFont font, bool in_math_environment=false, FontSubclass subclass=FontSubclass::Default) const; + QPair getFontData(JKQTMathTextEnvironmentFont font, bool in_math_environment=false) const; /*! \brief calls setFontRoman(), or calls useXITS() if \a __value \c =="XITS". calls useSTIX() if \a __value \c =="STIX", ... @@ -344,22 +342,18 @@ 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(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, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard); + void setFallbackFontGreek(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(JKQTMathTextEnvironmentFont font) const; + QString getFallbackFontGreek() 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(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, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard); + void setFallbackFontSymbols(const QString & fontName, JKQTMathTextFontEncoding encoding=JKQTMathTextFontEncoding::MTFEStandard); /** \brief retrieves the font to be used for symbols in the logical font \a font */ - QString getSymbolfontSymbol(JKQTMathTextEnvironmentFont font) const; + QString getFallbackFontSymbols() const; - /** \brief retrieves the encoding used for the symbol font to be used for symbols in the logical font \a font */ - 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 */ - JKQTMathTextFontEncoding getSymbolfontEncodingGreek(JKQTMathTextEnvironmentFont font) const; + /** \brief retrieves the encoding used for the symbol font to be used for symbols */ + JKQTMathTextFontEncoding getFontEncodingFallbackFontSymbols() const; + /** \brief retrieves the encoding used for the greek letter font to be used for greek letters */ + JKQTMathTextFontEncoding getFontEncodingFallbackFontGreek() const; /** \brief retrieves the encoding used for the script font */ JKQTMathTextFontEncoding getFontEncodingScript() const; /** \brief retrieves the encoding used for the Fraktur font */ @@ -430,7 +424,7 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject { * useAnyUnicode("Comic Sans MS", "Comic Sans MS"):
    \image html jkqtmathtext/jkqtmathparser_comicsans.png

    * */ - void useAnyUnicode(QString timesFont=QString(""), const QString& sansFont=QString(""), JKQTMathTextFontEncoding encodingTimes=JKQTMathTextFontEncoding::MTFEunicode, JKQTMathTextFontEncoding encodingSans=JKQTMathTextFontEncoding::MTFEunicode); + void useAnyUnicode(QString timesFont=QString(""), const QString& sansFont=QString(""), JKQTMathTextFontEncoding encodingTimes=JKQTMathTextFontEncoding::MTFEUnicode, JKQTMathTextFontEncoding encodingSans=JKQTMathTextFontEncoding::MTFEUnicode); diff --git a/lib/jkqtmathtext/jkqtmathtexttools.cpp b/lib/jkqtmathtext/jkqtmathtexttools.cpp index 6eb85eb005..0e898d6091 100644 --- a/lib/jkqtmathtext/jkqtmathtexttools.cpp +++ b/lib/jkqtmathtext/jkqtmathtexttools.cpp @@ -317,10 +317,9 @@ JKQTMathTextFontSpecifier JKQTMathTextFontSpecifier::getSTIXFamilies() QString JKQTMathTextFontEncoding2String(JKQTMathTextFontEncoding e) { switch(e) { - case MTFEunicode: return "MTFEunicode"; - case MTFEStandard: return "MTFEStandard"; - case MTFEunicodeLimited: return "MTFEunicodeLimited"; - case MTFEwinSymbol: return "MTFEwinSymbol"; + case MTFEUnicode: return "MTFEUnicode"; + case MTFEStandard: return "MTFELatin1"; + case MTFEWinSymbol: return "MTFEWinSymbol"; } return "???"; } @@ -429,6 +428,33 @@ JKQTMathTextEnvironment::JKQTMathTextEnvironment() { insideMath=false; } +JKQTMathTextFontEncoding JKQTMathTextEnvironment::getFontEncoding(JKQTMathText* parent) const { + switch (font) { + case MTEsans: if (insideMath) { + return parent->getFontEncodingMathSans(); + } else { + return parent->getFontEncodingSans(); + } + break; + case MTEmathSans: return parent->getFontEncodingMathSans(); break; + case MTEtypewriter: return parent->getFontEncodingTypewriter(); break; + case MTEscript: return parent->getFontEncodingScript(); break; + case MTEcaligraphic: return parent->getFontEncodingCaligraphic(); break; + case MTEblackboard: return parent->getFontEncodingBlackboard(); break; + case MTEfraktur: return parent->getFontEncodingFraktur(); break; + case MTEmathRoman: return parent->getFontEncodingMathRoman(); break; + case MTEroman: if (insideMath) { + return parent->getFontEncodingMathRoman(); + } else { + return parent->getFontEncodingRoman(); + } + break; + default: + return MTFEStandard; + } + return MTFEStandard; +} + QFont JKQTMathTextEnvironment::getFont(JKQTMathText* parent) const { QFont f; switch (font) { @@ -445,6 +471,9 @@ QFont JKQTMathTextEnvironment::getFont(JKQTMathText* parent) const { case MTEblackboard: f.setFamily(parent->getFontBlackboard()); break; case MTEfraktur: f.setFamily(parent->getFontFraktur()); break; case MTEmathRoman: f.setFamily(parent->getFontMathRoman()); break; + case MTEFallbackSymbols: f.setFamily(parent->getFallbackFontSymbols()); break; + case MTEFallbackGreek: f.setFamily(parent->getFallbackFontGreek()); break; + case MTECustomFont: f.setFamily(customFontName); break; default: case MTEroman: if (insideMath) { f.setFamily(parent->getFontMathRoman()); @@ -503,9 +532,7 @@ JKQTMathTextNodeSize::JKQTMathTextNodeSize(): JKQTMathTextFontDefinition::JKQTMathTextFontDefinition(): - fontName("Times New Roman"), fontEncoding(MTFEStandard), - symbolfontGreek("Symbol"), symbolfontGreekEncoding(MTFEwinSymbol), - symbolfontSymbol("Symbol"), symbolfontSymbolEncoding(MTFEwinSymbol) + fontName("Times New Roman"), fontEncoding(MTFEStandard) { } @@ -704,3 +731,17 @@ bool isPrintableJKQTMathTextBraceType(JKQTMathTextBraceType type) { return (type!=MTBTAny) && (type!=MTBTUnknown); } + +JKQTMathTextFontEncoding estimateJKQTMathTextFontEncoding(QFont font) +{ + font.setStyleStrategy(QFont::NoFontMerging); + const QString fontFamily=font.family().toLower(); + if (fontFamily=="symbol") return JKQTMathTextFontEncoding::MTFEWinSymbol; + if (fontFamily.startsWith("xits") || fontFamily.startsWith("stix")||fontFamily.startsWith("asana")) return JKQTMathTextFontEncoding::MTFEUnicode; + const QFontMetricsF fm(font); + if (fm.inFont(QChar(0x3B1))) return JKQTMathTextFontEncoding::MTFEUnicode; // griechisch alpha + if (fm.inFont(QChar(0x2192))) return JKQTMathTextFontEncoding::MTFEUnicode; // pfeil nach rechts + if (fm.inFont(QChar(0x2202))) return JKQTMathTextFontEncoding::MTFEUnicode; // partial + if (fm.inFont(QChar(0x2208))) return JKQTMathTextFontEncoding::MTFEUnicode; // element + return JKQTMathTextFontEncoding::MTFELatin1; +} diff --git a/lib/jkqtmathtext/jkqtmathtexttools.h b/lib/jkqtmathtext/jkqtmathtexttools.h index d2659e01df..9248ccc61f 100644 --- a/lib/jkqtmathtext/jkqtmathtexttools.h +++ b/lib/jkqtmathtext/jkqtmathtexttools.h @@ -126,12 +126,19 @@ private: * \ingroup jkqtmathtext_tools */ 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 http://www.stixfonts.org/)*/ - 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) */ + MTFEWinSymbol=0, /*!< \brief This assumes that symbols shall be taken from a MS Windows style Symbol font */ + MTFEUnicode=1, /*!< \brief This assumes that symbols shall be taken from a Unicode font, which ideally offers full symbol support (e.g. the XITS fonts, STIX fonts from http://www.stixfonts.org/)*/ + MTFELatin1=2, /*!< \brief the encoding of a standard Latin1 TTF font (i.e. we can only expect letters,number and not many special characters) */ + MTFEStandard=MTFELatin1 }; +/** \brief this function tries to determine the JKQTMathTextFontEncoding of a given font (HEURISTICS!!!) + * \ingroup jkqtmathtext_tools +*/ +JKQTMATHTEXT_LIB_EXPORT JKQTMathTextFontEncoding estimateJKQTMathTextFontEncoding(QFont font); + + + /** \brief convert MTfontEncoding to a string * \ingroup jkqtmathtext_tools */ @@ -213,7 +220,11 @@ enum JKQTMathTextEnvironmentFont { MTEcaligraphic, /*!< \brief caligraphic font, e.g. \\mathcal{} */ MTEfraktur, /*!< \brief fraktur font, e.g. \\mathfrak{} */ - MTenvironmentFontCount /*!< \brief internal enum value that allows to iterate over MTenvironmentFont \internal */ + MTEEnvironmentFontCount, /*!< \brief internal enum value that allows to iterate over MTenvironmentFont \internal */ + MTECurrentFont, /*!< \brief internal enum value that specifies that the currently set font shall be used \internal */ + MTECustomFont, /*!< \brief internal enum value that specifies that a custom font specified elsewhere shall be used \internal */ + MTEFallbackSymbols, /*!< \brief symbol font */ + MTEFallbackGreek, /*!< \brief greek letters font */ }; @@ -226,6 +237,8 @@ struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextEnvironment { QColor color; /** \brief current font */ JKQTMathTextEnvironmentFont font; + /** \brief custom font, when font==MTECustomFont */ + QString customFontName; /** \brief current font size [pt] */ double fontSize; /** \brief is the text currently bold? */ @@ -246,6 +259,8 @@ struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextEnvironment { /** \brief build a QFont object from the settings in this object */ QFont getFont(JKQTMathText* parent) const; + /** \brief return the encoding of the given Font */ + JKQTMathTextFontEncoding getFontEncoding(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) @@ -281,15 +296,6 @@ struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextFontDefinition { 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; }; diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp b/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp index 410ca67458..3bea5f77b8 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp +++ b/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.cpp @@ -35,861 +35,21 @@ - - - - JKQTMathTextSymbolNode::JKQTMathTextSymbolNode(JKQTMathText* _parent, const QString& name, bool _addWhitespace): JKQTMathTextNode(_parent), symbolName(name), addWhitespace(_addWhitespace) { + fillSymbolTables(); } -JKQTMathTextSymbolNode::~JKQTMathTextSymbolNode() = default; +JKQTMathTextSymbolNode::~JKQTMathTextSymbolNode() { + +} QString JKQTMathTextSymbolNode::getTypeName() const { return QLatin1String("JKQTMathTextSymbolNode(")+symbolName+QLatin1String(")"); } -bool JKQTMathTextSymbolNode::getWinSymbolProp(JKQTMathTextSymbolNode::SymbolProps& props, const QString &n, const JKQTMathTextEnvironment& currentEv, double mathFontFactor) const -{ - auto fnt=parentMathText->getFontData(currentEv.font, currentEv.insideMath, JKQTMathText::FontSubclass::Text); - auto fntSym=parentMathText->getFontData(currentEv.font, currentEv.insideMath, JKQTMathText::FontSubclass::Symbols); - - //qDebug()<<" +--- getWinSymbolProp("< winSymbolSymbol; - if (winSymbolSymbol.isEmpty()) { - winSymbolSymbol.insert("leftrightarrow", QChar(0xAB)); - winSymbolSymbol.insert("leftarrow", QChar(0xAC)); - winSymbolSymbol.insert("rightarrow", QChar(0xAE)); - winSymbolSymbol.insert("to", QChar(0xAE)); - winSymbolSymbol.insert("uparrow", QChar(0xAD)); - winSymbolSymbol.insert("downarrow", QChar(0xAF)); - winSymbolSymbol.insert("Leftrightarrow", QChar(0xDB)); - winSymbolSymbol.insert("iff", QChar(0xDB)); - winSymbolSymbol.insert("Leftarrow", QChar(0xDC)); - winSymbolSymbol.insert("Rightarrow", QChar(0xDE)); - winSymbolSymbol.insert("Uparrow", QChar(0xDD)); - winSymbolSymbol.insert("Downarrow", QChar(0xFF)); - winSymbolSymbol.insert("pm", QChar(0xB1)); - winSymbolSymbol.insert("leq", QChar(0xA3)); - winSymbolSymbol.insert("geq", QChar(0xB3)); - winSymbolSymbol.insert("le", QChar(0xA3)); - winSymbolSymbol.insert("ge", QChar(0xB3)); - winSymbolSymbol.insert("times", QChar(0xB4)); - winSymbolSymbol.insert("propto", QChar(0xB5)); - winSymbolSymbol.insert("partial", QChar(0xB6)); - winSymbolSymbol.insert("bullet", QChar(0xB7)); - winSymbolSymbol.insert("neq", QChar(0xB9)); - winSymbolSymbol.insert("ne", QChar(0xB9)); - winSymbolSymbol.insert("equiv", QChar(0xBA)); - winSymbolSymbol.insert("approx", QChar(0xBB)); - winSymbolSymbol.insert("ellipsis", QChar(0xBC)); - winSymbolSymbol.insert("Im", QChar(0xC1)); - winSymbolSymbol.insert("Re", QChar(0xC2)); - winSymbolSymbol.insert("otimes", QChar(0xC4)); - winSymbolSymbol.insert("oplus", QChar(0xC5)); - winSymbolSymbol.insert("oslash", QChar(0xC6)); - winSymbolSymbol.insert("cap", QChar(0xC7)); - winSymbolSymbol.insert("land", QChar(0xC7)); - winSymbolSymbol.insert("cup", QChar(0xC8)); - winSymbolSymbol.insert("lor", QChar(0xC8)); - winSymbolSymbol.insert("supset", QChar(0xC9)); - winSymbolSymbol.insert("supseteq", QChar(0xCA)); - winSymbolSymbol.insert("supsetnot", QChar(0xCB)); - winSymbolSymbol.insert("subset", QChar(0xCC)); - winSymbolSymbol.insert("subseteq", QChar(0xCD)); - winSymbolSymbol.insert("in", QChar(0xCE)); - winSymbolSymbol.insert("notin", QChar(0xCF)); - winSymbolSymbol.insert("angle", QChar(0xD0)); - winSymbolSymbol.insert("nabla", QChar(0xD1)); - winSymbolSymbol.insert("copyright", QChar(0xD3)); - winSymbolSymbol.insert("registered", QChar(0xD2)); - winSymbolSymbol.insert("circledR", QChar(0xD2)); - winSymbolSymbol.insert("trademark", QChar(0xD4)); - winSymbolSymbol.insert("textregistered", QChar(0xD4)); - winSymbolSymbol.insert("cdot", QChar(0xD7)); - winSymbolSymbol.insert("neg", QChar(0xD8)); - winSymbolSymbol.insert("wedge", QChar(0xD9)); - winSymbolSymbol.insert("vee", QChar(0xDA)); - winSymbolSymbol.insert("diamond", QChar(0xE0)); - winSymbolSymbol.insert("langle", QChar(0xE1)); - winSymbolSymbol.insert("rangle", QChar(0xF1)); - winSymbolSymbol.insert("forall", QChar(0x22)); - winSymbolSymbol.insert("exists", QChar(0x24)); - winSymbolSymbol.insert("cong", QChar(0x40)); - winSymbolSymbol.insert("bot", QChar(0x5E)); - winSymbolSymbol.insert("ll", "<<"); - winSymbolSymbol.insert("gg", ">>"); - winSymbolSymbol.insert("Alef", QChar(0xC0)); - winSymbolSymbol.insert("alef", QChar(0xC0)); - winSymbolSymbol.insert("tilde", "~"); - winSymbolSymbol.insert("emptyset", QChar(0xC6)); - winSymbolSymbol.insert("varnothing", QChar(0xC6)); - winSymbolSymbol.insert("lceil", QChar(0xE9)); - winSymbolSymbol.insert("rceil", QChar(0xF9)); - winSymbolSymbol.insert("lfloor", QChar(0xEB)); - winSymbolSymbol.insert("rfloor", QChar(0xFB)); - winSymbolSymbol.insert("subsetnot", QChar(0xCB)); - winSymbolSymbol.insert("DC", "="); - winSymbolSymbol.insert("mid", "|"); - winSymbolSymbol.insert("cdots", QString(3, QChar(0xD7))); - winSymbolSymbol.insert("dots", QChar(0xDC)); - winSymbolSymbol.insert("ldots", QChar(0xDC)); - winSymbolSymbol.insert("cent", "c"); - winSymbolSymbol.insert("sim", QChar(0x7E)); - winSymbolSymbol.insert("infty", QChar(0xA5)); - } - - QHash::iterator itsymbol = winSymbolSymbol.find(n); - if (itsymbol!=winSymbolSymbol.end()) { - props.symbol = itsymbol.value(); - } else if (n == "int") { props.symbol = QChar(0xF2); props.fontFactor = mathFontFactor; props.yfactor = +0.1; } - else if (n == "bbC") { props.symbol = "C"; props.bold = +1; props.italic = -1; } - else if (n == "bbH") { props.symbol = "H"; props.bold = +1; props.italic = -1; } - else if (n == "bbN") { props.symbol = "N"; props.bold = +1; props.italic = -1; } - else if (n == "bbP") { props.symbol = "P"; props.bold = +1; props.italic = -1; } - else if (n == "bbQ") { props.symbol = "Q"; props.bold = +1; props.italic = -1; } - else if (n == "bbR") { props.symbol = "R"; props.bold = +1; props.italic = -1; } - else if (n == "bbZ") { props.symbol = "Z"; props.bold = +1; props.italic = -1; } - else if (n == "iint") { props.symbol = QString(2, QChar(0xF2)); props.fontFactor = mathFontFactor; props.yfactor = +0.1; } - else if (n == "iiint") { props.symbol = QString(3, QChar(0xF2)); props.fontFactor = mathFontFactor; props.yfactor = +0.1; } - else if (n == "bigcap") { props.symbol = QChar(0xC7); props.fontFactor = 2; } - else if (n == "bigcup") { props.symbol = QChar(0xC8); props.fontFactor = 2; } - else if (n == "bigvee") { props.symbol = QChar(0xDA); props.fontFactor = 2; } - else if (n == "bighat") { props.symbol = QChar(0xD9); props.fontFactor = 2; } - - else { // here are text mode symbols, i.e. bold and italic won't be touched - props.bold = -1; - props.italic = -1; - props.font = fnt.first; - if (n == "_") { props.symbol = "_"; props.bold = 0; props.italic = 0; } - else if (n == "}") { props.symbol = "}"; props.italic=-1; } - else if (n == "{") { props.symbol = "{"; props.italic=-1; } - else if (n == "]") { props.symbol = "]"; props.italic=-1; } - else if (n == "[") { props.symbol = "["; props.italic=-1; } - else if (n == "(") { props.symbol = "("; props.italic=-1; } - else if (n == ")") { props.symbol = ")"; props.italic=-1; } - else if (n == "|") { props.symbol = "|"; props.italic=-1; } - else if (n == "hbar") { props.symbol = "h"; props.bold = 0; props.italic = 0; props.drawBar = true; } - else if (n == "euro") { props.symbol = ""; props.bold = 0; props.italic = 0; } - else if (n == "cent") { props.symbol = QChar(0xA2); props.bold = 0; props.italic = 0; } - else if (n == "pound") { props.symbol = QChar(0xA3); props.bold = 0; props.italic = 0; } - else if (n == "yen") { props.symbol = QChar(0xA5); props.bold = 0; props.italic = 0; } - else if (n == "div") { props.symbol = QChar(0xF7); props.bold = 0; props.italic = 0; } - else if (n == "backslash") { props.symbol = "\\"; props.bold = 0; props.italic = 0; } - //else if (n=="|") { symbol="||"; bold=0; 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 == ">") { 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; } - else if (n == "grqq") { props.symbol = "\""; props.bold = 0; props.italic = 0; } - else if (n == "flq") { props.symbol = "<"; props.bold = 0; props.italic = 0; } - else if (n == "frq") { props.symbol = ">"; props.bold = 0; props.italic = 0; } - else if (n == "flqq") { props.symbol = QChar(0xAB); props.bold = 0; props.italic = 0; } - else if (n == "frqq") { props.symbol = QChar(0xBB); props.bold = 0; props.italic = 0; } - else if (n == "prime") { props.symbol = "'"; props.bold = 0; props.italic = 0; } - else if (n == "dprime") { props.symbol = "''"; props.bold = 0; props.italic = 0; } - else if (n == "trprime") { props.symbol = "'''"; props.bold = 0; props.italic = 0; } - else { return false; } - } - - return true; -} - -bool JKQTMathTextSymbolNode::getGreekSymbolProp(JKQTMathTextSymbolNode::SymbolProps& props, const QString &n, const JKQTMathTextEnvironment& currentEv, double mathFontFactor) const -{ - auto fnt=parentMathText->getFontData(currentEv.font, currentEv.insideMath, JKQTMathText::FontSubclass::Text); - auto fntGreek=parentMathText->getFontData(currentEv.font, currentEv.insideMath, JKQTMathText::FontSubclass::Greek); - - //qDebug()<<" +--- getGreekSymbolProp("< winSymbolGreek; - if (winSymbolGreek.isEmpty()) { - winSymbolGreek.insert("alpha", "a"); - winSymbolGreek.insert("beta", "b"); - winSymbolGreek.insert("gamma", "g"); - winSymbolGreek.insert("delta", "d"); - winSymbolGreek.insert("epsilon", "e"); - winSymbolGreek.insert("varepsilon", "e"); - winSymbolGreek.insert("zeta", "z"); - winSymbolGreek.insert("eta", "h"); - winSymbolGreek.insert("theta", "q"); - winSymbolGreek.insert("vartheta", "J"); - winSymbolGreek.insert("iota", "i"); - winSymbolGreek.insert("kappa", "k"); - winSymbolGreek.insert("lambda", "l"); - winSymbolGreek.insert("mu", "m"); - winSymbolGreek.insert("nu", "n"); - winSymbolGreek.insert("xi", "x"); - winSymbolGreek.insert("pi", "p"); - winSymbolGreek.insert("varpi", "v"); - winSymbolGreek.insert("rho", "r"); - winSymbolGreek.insert("sigma", "s"); - winSymbolGreek.insert("varsigma", "V"); - winSymbolGreek.insert("tau", "t"); - winSymbolGreek.insert("upsilon", "u"); - winSymbolGreek.insert("phi", "f"); - winSymbolGreek.insert("varphi", "j"); - winSymbolGreek.insert("chi", "c"); - winSymbolGreek.insert("psi", "y"); - winSymbolGreek.insert("omega", "w"); - winSymbolGreek.insert("Gamma", "G"); - winSymbolGreek.insert("Delta", "D"); - winSymbolGreek.insert("Theta", "Q"); - winSymbolGreek.insert("Lambda", "L"); - winSymbolGreek.insert("Omega", "W"); - winSymbolGreek.insert("Xi", "X"); - winSymbolGreek.insert("Pi", "P"); - winSymbolGreek.insert("Sigma", "S"); - winSymbolGreek.insert("Upsilon", ""); - winSymbolGreek.insert("Phi", "F"); - winSymbolGreek.insert("Psi", "Y"); - } - - static QHash unicodeGreek; - if (unicodeGreek.isEmpty()) { - unicodeGreek.insert("alpha", QChar(0x3B1)); - unicodeGreek.insert("beta", QChar(0x3B2)); - unicodeGreek.insert("gamma", QChar(0x3B3)); - unicodeGreek.insert("delta", QChar(0x3B4)); - unicodeGreek.insert("epsilon", QChar(0x3B5)); - unicodeGreek.insert("varepsilon", QChar(0x3B5)); - unicodeGreek.insert("zeta", QChar(0x3B6)); - unicodeGreek.insert("eta", QChar(0x3B7)); - unicodeGreek.insert("theta", QChar(0x3B8)); - unicodeGreek.insert("vartheta", QChar(0x3D1)); - unicodeGreek.insert("iota", QChar(0x3B9)); - unicodeGreek.insert("kappa", QChar(0x3BA)); - unicodeGreek.insert("lambda", QChar(0x3BB)); - unicodeGreek.insert("mu", QChar(0x3BC)); - unicodeGreek.insert("nu", QChar(0x3BD)); - unicodeGreek.insert("xi", QChar(0x3BE)); - unicodeGreek.insert("pi", QChar(0x3C0)); - unicodeGreek.insert("varpi", QChar(0x3D6)); - unicodeGreek.insert("rho", QChar(0x3C1)); - unicodeGreek.insert("varrho", QChar(0x3F1)); - unicodeGreek.insert("sigma", QChar(0x3C3)); - unicodeGreek.insert("varsigma", QChar(0x3C2)); - unicodeGreek.insert("tau", QChar(0x3C4)); - unicodeGreek.insert("upsilon", QChar(0x3C5)); - unicodeGreek.insert("phi", QChar(0x3D5)); - unicodeGreek.insert("varphi", QChar(0x3C6)); - unicodeGreek.insert("chi", QChar(0x3C7)); - unicodeGreek.insert("psi", QChar(0x3C8)); - unicodeGreek.insert("omega", QChar(0x3C9)); - unicodeGreek.insert("Omega", QChar(0x3A9)); - unicodeGreek.insert("Gamma", QChar(0x393)); - unicodeGreek.insert("Delta", QChar(0x394)); - unicodeGreek.insert("Theta", QChar(0x398)); - unicodeGreek.insert("Lambda", QChar(0x39B)); - unicodeGreek.insert("Xi", QChar(0x39E)); - unicodeGreek.insert("Pi", QChar(0x3A0)); - unicodeGreek.insert("prod", QChar(0x3A0)); - unicodeGreek.insert("Sigma", QChar(0x3A3)); - unicodeGreek.insert("sum", QChar(0x3A3)); - unicodeGreek.insert("Upsilon", QChar(0x3A5)); - unicodeGreek.insert("Phi", QChar(0x3A6)); - unicodeGreek.insert("Psi", QChar(0x3A8)); - } - - //qDebug()<<"##SEARCHING "<::iterator itgreek = unicodeGreek.find(n); - if (itgreek!=unicodeGreek.end()) { - //qDebug()<<"##SEARCHING "<::iterator itgreek = unicodeGreek.find(n); - if (itgreek!=unicodeGreek.end()) { - //qDebug()<<"##SEARCHING "<::iterator itgreek = winSymbolGreek.find(n); - if (itgreek!=winSymbolGreek.end()) { - props.symbol = itgreek.value(); - //qDebug()<<"##SEARCHING "<") { 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 == "]") { 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 = "&"; } - else if (n == "#") { props.symbol = "#"; } - else if (n == "ast") { props.symbol = "*"; } - else if (n == "dots") { props.symbol = "..."; } - else if (n == "ldots") { props.symbol = "..."; } - else if (n == "colon") { props.symbol = ":"; } - - else {return false;} - return true; -} - -bool JKQTMathTextSymbolNode::getUnicodeBaseSymbolProp(JKQTMathTextSymbolNode::SymbolProps& props, const QString &n) const -{ - - //qDebug()<<"--- getUnicodeBaseSymbolProp("< unicodeBaseSymbol; - if (unicodeBaseSymbol.isEmpty()) { - - unicodeBaseSymbol.insert("diamond", QChar(0xE0)); - 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)); - unicodeBaseSymbol.insert("circledR", QChar(0x00AE)); - unicodeBaseSymbol.insert("trademark", QChar(0x2122)); - unicodeBaseSymbol.insert("textregistered", QChar(0x2122)); - unicodeBaseSymbol.insert("cdot", QChar(0x00B7)); - unicodeBaseSymbol.insert("pm", QChar(0x00B1)); - unicodeBaseSymbol.insert("leq", QChar(0x2264)); - unicodeBaseSymbol.insert("geq", QChar(0x2265)); - unicodeBaseSymbol.insert("le", QChar(0x2264)); - unicodeBaseSymbol.insert("ge", QChar(0x2265)); - unicodeBaseSymbol.insert("hbar", QChar(0x210F)); - unicodeBaseSymbol.insert("EUR", QChar(0x20AC)); - unicodeBaseSymbol.insert("euro", QChar(0x20AC)); - unicodeBaseSymbol.insert("circ", QChar(0x2218)); - unicodeBaseSymbol.insert("cent", QChar(0x00A2)); - unicodeBaseSymbol.insert("pound", QChar(0x00A3)); - unicodeBaseSymbol.insert("yen", QChar(0x00A5)); - unicodeBaseSymbol.insert("dollar", QChar(0x0024)); - unicodeBaseSymbol.insert("neq", QChar(0x2260)); - unicodeBaseSymbol.insert("lnot", QChar(0x2260)); - unicodeBaseSymbol.insert("Angstrom", QChar(0x00AC)); - unicodeBaseSymbol.insert("co", QChar(0x2105)); - unicodeBaseSymbol.insert("No", QChar(0x2116)); - unicodeBaseSymbol.insert("Ohm", QChar(0x2126)); - unicodeBaseSymbol.insert("ohm", QChar(0x2126)); - unicodeBaseSymbol.insert("tcohm", QChar(0x2126)); - unicodeBaseSymbol.insert("partial", QChar(0x2202)); - 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); - if (itbasesymbol!=unicodeBaseSymbol.end()) { - props.symbol = itbasesymbol.value(); - //qDebug()<<"### found "< unicodeSymbol; - if (unicodeSymbol.isEmpty()) { - unicodeSymbol.insert("leftrightarrow", QChar(0x2194)); - unicodeSymbol.insert("leftarrow", QChar(0x2190)); - unicodeSymbol.insert("rightarrow", QChar(0x2192)); - unicodeSymbol.insert("to", QChar(0x2192)); - unicodeSymbol.insert("uparrow", QChar(0x2191)); - unicodeSymbol.insert("downarrow", QChar(0x2193)); - unicodeSymbol.insert("updownarrow", QChar(0x2195)); - unicodeSymbol.insert("Leftrightarrow", QChar(0x21D4)); - unicodeSymbol.insert("iff", QChar(0x21D4)); - unicodeSymbol.insert("Leftarrow", QChar(0x21D0)); - unicodeSymbol.insert("Rightarrow", QChar(0x21D2)); - unicodeSymbol.insert("Uparrow", QChar(0x21D1)); - unicodeSymbol.insert("Downarrow", QChar(0x21D3)); - unicodeSymbol.insert("Updownarrow", QChar(0x21D5)); - unicodeSymbol.insert("mp", QChar(0x2213)); - unicodeSymbol.insert("ll", QChar(0x226A)); - unicodeSymbol.insert("gg", QChar(0x226B)); - unicodeSymbol.insert("Alef", QChar(0x2135)); - unicodeSymbol.insert("Aleph", QChar(0x2135)); - unicodeSymbol.insert("Bet", QChar(0x2136)); - unicodeSymbol.insert("Beth", QChar(0x2136)); - unicodeSymbol.insert("Gimel", QChar(0x2137)); - unicodeSymbol.insert("Dalet", QChar(0x2138)); - unicodeSymbol.insert("alef", QChar(0x2135)); - unicodeSymbol.insert("aleph", QChar(0x2135)); - unicodeSymbol.insert("bet", QChar(0x2136)); - unicodeSymbol.insert("beth", QChar(0x2136)); - unicodeSymbol.insert("gimel", QChar(0x2137)); - unicodeSymbol.insert("dalet", QChar(0x2138)); - unicodeSymbol.insert("nexists", QChar(0x2204)); - unicodeSymbol.insert("ni", QChar(0x220B)); - unicodeSymbol.insert("notni", QChar(0x220C)); - unicodeSymbol.insert("tilde", QChar(0x223C)); - unicodeSymbol.insert("sim", QChar(0x223C)); - unicodeSymbol.insert("emptyset", QChar(0x2300)); - unicodeSymbol.insert("varnothing", QChar(0x2300)); - unicodeSymbol.insert("odot", QChar(0x2299)); - unicodeSymbol.insert("ominus", QChar(0x2296)); - unicodeSymbol.insert("lceil", QChar(0x2308)); - 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)); - unicodeSymbol.insert("perp", QChar(0x22A5)); - unicodeSymbol.insert("sqcap", QChar(0x2293)); - unicodeSymbol.insert("sqcup", QChar(0x2294)); - unicodeSymbol.insert("triangle", QChar(0x2206)); - unicodeSymbol.insert("square", QChar(0x25A1)); - unicodeSymbol.insert("setminus", QChar(0x2216)); - unicodeSymbol.insert("mid", QChar(0x2223)); - unicodeSymbol.insert("nmid", QChar(0x2224)); - unicodeSymbol.insert("vdots", QChar(0x22EE)); - unicodeSymbol.insert("iddots", QChar(0x22F0)); - unicodeSymbol.insert("ddots", QChar(0x22F1)); - unicodeSymbol.insert("perthousand", QChar(0x2030)); - unicodeSymbol.insert("leftharpoonup", QChar(0x21BC)); - unicodeSymbol.insert("rightharpoonup", QChar(0x21C0)); - unicodeSymbol.insert("upharpoonleft", QChar(0x21BF)); - unicodeSymbol.insert("downharpoonleft", QChar(0x21C3)); - unicodeSymbol.insert("leftrightharpoon", QChar(0x21CB)); - unicodeSymbol.insert("rightleftharpoon", QChar(0x21CC)); - unicodeSymbol.insert("leftharpoondown", QChar(0x21BD)); - unicodeSymbol.insert("rightharpoondown", QChar(0x21C1)); - unicodeSymbol.insert("upharpoonright", QChar(0x21BE)); - unicodeSymbol.insert("downharpoonright", QChar(0x21C2)); - unicodeSymbol.insert("nwarrow", QChar(0x2196)); - unicodeSymbol.insert("nearrow", QChar(0x2197)); - unicodeSymbol.insert("searrow", QChar(0x2198)); - unicodeSymbol.insert("swarrow", QChar(0x2199)); - unicodeSymbol.insert("mapsto", QChar(0x21A6)); - unicodeSymbol.insert("div", QChar(0x00F7)); - unicodeSymbol.insert("multimap", QChar(0x22B8)); - unicodeSymbol.insert("maporiginal", QChar(0x22B6)); - unicodeSymbol.insert("mapimage", QChar(0x22B7)); - unicodeSymbol.insert("benzene", QChar(0x232C)); - unicodeSymbol.insert("propto", QChar(0x221D)); - unicodeSymbol.insert("ne", QChar(0x2260)); - unicodeSymbol.insert("equiv", QChar(0x2261)); - unicodeSymbol.insert("ellipsis", QChar(0x2026)); - unicodeSymbol.insert("Im", QChar(0x2111)); - unicodeSymbol.insert("Re", QChar(0x211C)); - unicodeSymbol.insert("otimes", QChar(0x2297)); - unicodeSymbol.insert("oplus", QChar(0x2295)); - unicodeSymbol.insert("oslash", QChar(0x2298)); - unicodeSymbol.insert("cap", QChar(0x2229)); - unicodeSymbol.insert("land", QChar(0x2229)); - unicodeSymbol.insert("cup", QChar(0x222A)); - unicodeSymbol.insert("lor", QChar(0x222A)); - unicodeSymbol.insert("supset", QChar(0x2283)); - unicodeSymbol.insert("supseteq", QChar(0x2286)); - unicodeSymbol.insert("supsetnot", QChar(0x2285)); - unicodeSymbol.insert("subset", QChar(0x2282)); - unicodeSymbol.insert("subseteq", QChar(0x2286)); - unicodeSymbol.insert("in", QChar(0x2208)); - unicodeSymbol.insert("notin", QChar(0x2209)); - unicodeSymbol.insert("angle", QChar(0x2220)); - unicodeSymbol.insert("measuredangle", QChar(0x2221)); - unicodeSymbol.insert("sphericalangle", QChar(0x2222)); - unicodeSymbol.insert("rightangle", QChar(0x221F)); - unicodeSymbol.insert("nabla", QChar(0x2207)); - unicodeSymbol.insert("parallel", QChar(0x2225)); - unicodeSymbol.insert("nparallel", QChar(0x2226)); - unicodeSymbol.insert("neg", QChar(0x00AC)); - unicodeSymbol.insert("wedge", QChar(0x2227)); - unicodeSymbol.insert("vee", QChar(0x2228)); - unicodeSymbol.insert("langle", QChar(0x2329)); - unicodeSymbol.insert("rangle", QChar(0x232A)); - unicodeSymbol.insert("forall", QChar(0x2200)); - unicodeSymbol.insert("exists", QChar(0x2203)); - unicodeSymbol.insert("bot", QChar(0x22A5)); - unicodeSymbol.insert("geqq", QChar(0x2267)); - unicodeSymbol.insert("leqq", QChar(0x2266)); - unicodeSymbol.insert("prec", QChar(0x227A)); - unicodeSymbol.insert("succ", QChar(0x227B)); - unicodeSymbol.insert("vartriangleleft", QChar(0x22B2)); - unicodeSymbol.insert("cong", QChar(0x2245)); - unicodeSymbol.insert("simeq", QChar(0x2243)); - unicodeSymbol.insert("therefore", QChar(0x2234)); - unicodeSymbol.insert("because", QChar(0x2235)); - unicodeSymbol.insert("lightning", QChar(0x21AF)); - unicodeSymbol.insert("blacksquare", QChar(0x220E)); - unicodeSymbol.insert("Box", QChar(0x25A1)); - unicodeSymbol.insert("celsius", QChar(0x2103)); - unicodeSymbol.insert("AC", QChar(0x223F)); - unicodeSymbol.insert("frown", QChar(0x2322)); - unicodeSymbol.insert("smile", QChar(0x2323)); - unicodeSymbol.insert("smiley", QChar(0x233A)); - unicodeSymbol.insert("blacksmiley", QChar(0x233B)); - unicodeSymbol.insert("frownie", QChar(0x2639)); - unicodeSymbol.insert("varhexagonlrbonds", QChar(0x232C)); - unicodeSymbol.insert("hexagon", QChar(0x2394)); - unicodeSymbol.insert("varcarriagereturn", QChar(0x23CE)); - unicodeSymbol.insert("benzenr", QChar(0x23E3)); - unicodeSymbol.insert("trapezium", QChar(0x23E2)); - unicodeSymbol.insert("female", QChar(0x2640)); - unicodeSymbol.insert("male", QChar(0x2642)); - - unicodeSymbol.insert("accurrent", QChar(0x23E6)); - } - - QHash::iterator itsymbol = unicodeSymbol.find(n); - - if (itsymbol!=unicodeSymbol.end()) { - props.symbol = itsymbol.value(); - } - else if (n == "sum") { props.symbol = QChar(0x2211); props.heightIsAscent = true; props.exactAscent = true; } - else if (n == "prod") { props.symbol = QChar(0x220F); props.heightIsAscent = true; props.exactAscent = true; } - else if (n == "bbC") { props.symbol = QChar(0x2102); props.italic = -1; } - else if (n == "bbH") { props.symbol = QChar(0x210D); props.italic = -1; } - else if (n == "bbN") { props.symbol = QChar(0x2115); props.italic = -1; } - else if (n == "bbP") { props.symbol = QChar(0x2119); props.italic = -1; } - else if (n == "bbQ") { props.symbol = QChar(0x211A); props.italic = -1; } - else if (n == "bbR") { props.symbol = QChar(0x211D); props.italic = -1; } - else if (n == "bbZ") { props.symbol = QChar(0x2124); props.italic = -1; } - else if (n == "iint") { props.symbol = QChar(0x222C); props.fontFactor = mathFontFactor; /*yfactor=+0.1;*/ props.heightIsAscent = true; props.exactAscent = true; } - else if (n == "iiint") { props.symbol = QChar(0x222D); props.fontFactor = mathFontFactor; /*yfactor=+0.1;*/ props.heightIsAscent = true; props.exactAscent = true; } - else if (n == "oint") { props.symbol = QChar(0x222E); props.fontFactor = mathFontFactor; /*yfactor=+0.1;*/ props.heightIsAscent = true; props.exactAscent = true; } - else if (n == "oiint") { props.symbol = QChar(0x222F); props.fontFactor = mathFontFactor; /*yfactor=+0.1;*/ props.heightIsAscent = true; props.exactAscent = true; } - else if (n == "oiiint") { props.symbol = QChar(0x2230); props.fontFactor = mathFontFactor; /*yfactor=+0.1;*/ props.heightIsAscent = true; props.exactAscent = true; } - else if (n == "coprod") { props.symbol = QChar(0x2210); props.heightIsAscent = true; props.exactAscent = true; } - else if (n == "bigcap") { props.symbol = QChar(0x22C2); props.heightIsAscent = true; props.exactAscent = true; } - else if (n == "bigcup") { props.symbol = QChar(0x22C3); props.heightIsAscent = true; props.exactAscent = true; } - else if (n == "bigvee") { props.symbol = QChar(0x22C1); props.heightIsAscent = true; props.exactAscent = true; } - else if (n == "bighat") { props.symbol = QChar(0x22C0); props.heightIsAscent = true; props.exactAscent = true; } - else if (n == "int") { props.symbol = QChar(0x222B); props.fontFactor = mathFontFactor; /*yfactor=+0.1;*/ props.heightIsAscent = true; props.exactAscent = true; } - else {return false;} - return true; -} - -bool JKQTMathTextSymbolNode::getSymbolProp(JKQTMathTextSymbolNode::SymbolProps& props, const QString &n, const JKQTMathTextEnvironment& currentEv, double mathFontFactor) const -{ - auto fnt=parentMathText->getFontData(currentEv.font, currentEv.insideMath, JKQTMathText::FontSubclass::Text); - auto fntGreek=parentMathText->getFontData(currentEv.font, currentEv.insideMath, JKQTMathText::FontSubclass::Greek); - auto fntSym=parentMathText->getFontData(currentEv.font, currentEv.insideMath, JKQTMathText::FontSubclass::Symbols); - - //qDebug()<<"--- getSymbolProp("<getFontData(currentEv.font, currentEv.insideMath, JKQTMathText::FontSubclass::Text); - auto fntSym=parentMathText->getFontData(currentEv.font, currentEv.insideMath, JKQTMathText::FontSubclass::Symbols); - auto fntGreek=parentMathText->getFontData(currentEv.font, currentEv.insideMath, JKQTMathText::FontSubclass::Greek); - - JKQTMathTextSymbolNode::SymbolProps props; - double mathFontFactor=1.8; - props.symbol=""; - props.fontFactor=1.0; - props.bold=0; - props.italic=-1; - props.yfactor=0; - props.drawBar=false; - props.font=fnt.first; - props.heightIsAscent=false; - props.exactAscent=false; - props.extendWidthInMathmode=false; - - QString n=symName; - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // statische Lookup-Tabellen vorbereiten - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - static QStringList extendWInMM; - if (extendWInMM.isEmpty()) { - extendWInMM <<"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"<<"mid"<<"+"<<"-"<<"|"<<"*"<<"/"<<"<"<<">"<<"="; - } - - if (extendWInMM.contains(n)) { - props.extendWidthInMathmode=true; - } - - - static QHash simpleTranslations; - if (simpleTranslations.isEmpty()) { - simpleTranslations.insert("", " "); - simpleTranslations.insert("sin", "sin"); - simpleTranslations.insert("cos", "cos"); - simpleTranslations.insert("tan", "tan"); - simpleTranslations.insert("sinh", "sinh"); - simpleTranslations.insert("cosh", "cosh"); - simpleTranslations.insert("tanh", "tanh"); - simpleTranslations.insert("atan", "atan"); - simpleTranslations.insert("acos", "acos"); - simpleTranslations.insert("asin", "asin"); - simpleTranslations.insert("arcsin", "arcsin"); - simpleTranslations.insert("arccos", "arccos"); - simpleTranslations.insert("arctan", "arctan"); - simpleTranslations.insert("degree", QLatin1String("\xB0")); - simpleTranslations.insert("textdegree ", QLatin1String("\xB0")); - simpleTranslations.insert("ii", "i"); - simpleTranslations.insert("dd", "d"); - simpleTranslations.insert("exp", "exp"); - simpleTranslations.insert("log", "log"); - simpleTranslations.insert("ln", "ln"); - simpleTranslations.insert("ld", "ld"); - simpleTranslations.insert("lb", "lb"); - simpleTranslations.insert("argmin", "argmin"); - simpleTranslations.insert("argmax", "argmax"); - simpleTranslations.insert("max", "max"); - simpleTranslations.insert("mod", "mod"); - simpleTranslations.insert("min", "min"); - simpleTranslations.insert("median", "median"); - simpleTranslations.insert("sign", "sign"); - simpleTranslations.insert("sgn", "sgn"); - simpleTranslations.insert("sec", "sec"); - simpleTranslations.insert("gcd", "gcd"); - simpleTranslations.insert("hom", "hom"); - simpleTranslations.insert("ker", "ker"); - simpleTranslations.insert("dim", "dim"); - simpleTranslations.insert("cot", "cot"); - simpleTranslations.insert("arg", "arg"); - simpleTranslations.insert("det", "det"); - simpleTranslations.insert("deg", "deg"); - simpleTranslations.insert("Pr", "Pr"); - simpleTranslations.insert("coth", "coth"); - } - - - static QHash simpleTranslations_heightIsAscent; - if (simpleTranslations_heightIsAscent.isEmpty()) { - simpleTranslations_heightIsAscent.insert("erf", "erf"); - simpleTranslations_heightIsAscent.insert("median", "median"); - simpleTranslations_heightIsAscent.insert("min", "min"); - simpleTranslations_heightIsAscent.insert("max", "max"); - simpleTranslations_heightIsAscent.insert("inf", "inf"); - simpleTranslations_heightIsAscent.insert("sup", "sup"); - simpleTranslations_heightIsAscent.insert("liminf", "liminf"); - simpleTranslations_heightIsAscent.insert("limsup", "limsup"); - simpleTranslations_heightIsAscent.insert("lim", "lim"); - } - - - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - props.font=fnt.first; - QString errorExplanation=""; - QHash::iterator itsimple = simpleTranslations.find(n); - if (itsimple!= simpleTranslations.end()) { - props.symbol=itsimple.value(); - } else { - QHash::iterator itsimplehia = simpleTranslations_heightIsAscent.find(n); - 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+"["+JKQTMathTextFontEncoding2String(fnt.second)+"] / sym:"+fntSym.first+"["+JKQTMathTextFontEncoding2String(fntSym.second)+"] / grk:"+fntGreek.first+"["+JKQTMathTextFontEncoding2String(fntGreek.second)+"]"; - } - } - } - if (addWhitespace) props.symbol+=" "; - - static QSet extraSymbolName = { - "infty", - "|", " ", "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)) { - parentMathText->addToErrorList(QObject::tr("unknown symbol '%1' found (%2)!").arg(n).arg(errorExplanation)); - } - - //qDebug()<0) f.setItalic(true); - if (props.bold<0) f.setBold(false); - if (props.bold>0) f.setBold(true); - const QFontMetricsF fm(f, painter.device()); - QString symb=props.symbol; - width=0; - if (currentEv.insideMath) { - width=qMax(JKQTMathTextGetTightBoundingRect(f, symb, painter.device()).width(), JKQTMathTextGetTightBoundingRect(f, "(", painter.device()).width()); - } else width=fm.boundingRect(symb).width();//fm.width(symbol); + const auto fullProps=symbols.value(symbolName, SymbolFullProps()); + const GlobalSymbolFlags globalFlags=fullProps.globalFlags; + const auto drawProps=fullProps.getDrawingData(currentEv, parentMathText); + const QFont f=drawProps.first; + const QFontMetricsF fm(f); + const JKQTMathTextSymbolNode::SymbolProps symprops=drawProps.second; + const SymbolFlags symflags=symprops.flags; + const QString sym=symprops.symbol; + const QRectF tbr=getTightBoundingRect(fm, sym, globalFlags); + const QRectF br=getBoundingRect(fm, sym, globalFlags); + const QRectF tbrNoSymbol=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()); + const QRectF mintbr=JKQTMathTextGetTightBoundingRect(f, "(", painter.device()); + const double yShift=symprops.yShiftFactor*tbr.height(); - if (symb.isEmpty()) { - width=fm.boundingRect("a").width(); - if (symbolName=="|") width=fm.boundingRect("1").width()*0.8; - else if (symbolName=="infty") width=JKQTMathTextGetTightBoundingRect(f, "8", painter.device()).height(); - else if (symbolName=="quad" || symbolName=="qquad") width=JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).width(); - else if (symbolName==" " || symbolName=="space") width=JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).width(); - else if (symbolName==";") width=JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).width()*0.75; - else if (symbolName==":") width=JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).width()*0.5; - else if (symbolName==",") width=JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).width()*0.25; - else if (symbolName=="!") width=-JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).width()*0.25; - else if (symbolName=="longleftarrow") { width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.5; symb="x"; } - else if (symbolName=="longrightarrow") { width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.5; symb="x"; } - else if (symbolName=="Longleftarrow") { width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.5; symb="x"; } - else if (symbolName=="Longrightarrow") { 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"; } - else if (symbolName=="Longleftrightarrow") { width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.5; symb="x"; } + + if (currentEv.insideMath) { + width=qMax(br.width(), mintbr.width()); + if (has(globalFlags, ExtendWidthInMathmode)) { + if (!symprops.getSymbolSingleChar().isNull()) width=width*parentMathText->getMathoperatorWidthFactor(); + else width=width+mintbr.width(); + } + } else { + width=br.width(); } - 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) { - //baselineHeight=fm.ascent()*0.8; + if (!sym.isEmpty()) { + overallHeight=tbr.height(); + baselineHeight=tbr.height()-tbr.bottom(); + } else { + overallHeight=tbrNoSymbol.height(); + baselineHeight=tbrNoSymbol.height()-tbrNoSymbol.bottom(); } - if (props.heightIsAscent) { - overallHeight=baselineHeight*1.1; - } - if (props.exactAscent && props.heightIsAscent) { - //qDebug()<getMathoperatorWidthFactor(); - - static QSet intCorrectionSymbolNames=QSet()<<"int"<<"iint"<<"iiint"<<"oint"<<"oiint"<<"oiiint"; - if (intCorrectionSymbolNames.contains(symbolName)) { + if (has(globalFlags, IntLikeSymbolCorrection)) { subSuperXCorrection=parentMathText->getIntSubSuperXCorrectionFactor()*tbr.width(); subBesidesXCorrection=parentMathText->getIntSubBesidesXCorrectionXFactor()*JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width(); } } +QRectF JKQTMathTextSymbolNode::getBoundingRect(const QFontMetricsF &fm, const QString &text, GlobalSymbolFlags globalFlags) +{ + if (has(globalFlags, MakeWhitespaceHalf) && text.contains(' ')) { + const QStringList str=text.simplified().trimmed().split(' '); + const QRectF brSp=fm.boundingRect("i"); + QRectF br; + for (int i=0; ibr.top()) { + br.setTop(lbr.top()); + } + if (lbr.bottom()br.top()) { + br.setTop(lbr.top()); + } + if (lbr.bottom()0) f.setItalic(true); - if (props.bold<0) f.setBold(false); - if (props.bold>0) f.setBold(true); - const QFontMetricsF fm(f, painter.device()); - painter.setFont(f); - double shift=0; - if (props.extendWidthInMathmode && currentEv.insideMath) { - const QRectF tbr=JKQTMathTextGetTightBoundingRect(f, props.symbol, painter.device()); - shift=0.5*width-tbr.width()/2.0-tbr.x(); - } + const auto fullProps=symbols.value(symbolName, SymbolFullProps()); + const GlobalSymbolFlags globalFlags=fullProps.globalFlags; + const auto drawProps=fullProps.getDrawingData(currentEv, parentMathText); + const QFont f=drawProps.first; + const QFontMetricsF fm(f); + const JKQTMathTextSymbolNode::SymbolProps symprops=drawProps.second; + const SymbolFlags symflags=symprops.flags; + const QString sym=symprops.symbol; + const QRectF tbr=getTightBoundingRect(fm, sym, globalFlags); + const QRectF br=getBoundingRect(fm, sym, globalFlags); + const QRectF tbrNoSymbol=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()); + const double yShift=symprops.yShiftFactor*tbr.height(); + const double xShift=(width-tbr.width())/2.0; + const QPointF x0(x+xShift-tbr.x(), y+yShift); - //std::cout<<"symbol '"<0) painter.drawLine(l); + painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); + painter.setFont(f); + painter.setPen(currentEv.color); + painter.translate(x0); + drawText(painter, sym, globalFlags); + if (has(symflags, DrawBar)) { + painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); + painter.setPen(QPen(currentEv.color, fm.lineWidth())); + const double ybar=0.66*tbr.top(); + painter.drawLine(br.width()-tbrNoSymbol.width()/2.0, ybar, br.width(), ybar); } - - // try to draw some often used special symbols, by synthesizing them from - // standard characters in the current drawing font - } else if (symbolName=="infty") { - //std::cout<<"draw infty\n"; - f1.setItalic(false); - const QFontMetricsF fm1(f1, painter.device()); - painter.setFont(f1); - painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); - painter.translate(x+shift+fm1.boundingRect("8").width()/3.0, y-fm1.xHeight()); - painter.rotate(90); - painter.drawText(QPointF(0,0), "8"); - - } else if (symbolName=="|") { - //std::cout<<"draw ||\n"; - f1.setItalic(false); - const QFontMetricsF fm1(f1, painter.device()); - painter.setFont(f1); - painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); - painter.translate(x+shift, y); - painter.drawText(QPointF(0,0), "|"); - painter.translate(fm1.boundingRect("8").width()/3.0, 0); - painter.drawText(QPointF(0,0), "|"); - - - // here are some spaces - } else if (symbolName==" ") { // full space (width of x) - } else if (symbolName=="space") { // full space (width of x) - } else if (symbolName=="qquad") { // full space(width of M) - } else if (symbolName=="quad") { // full space(width of M) - } else if (symbolName==";") { // 75% space - } else if (symbolName==":") { // 50% space - } else if (symbolName==",") { // 25% space - } else if (symbolName=="!") { // -25% space - } else if (symbolName=="longleftarrow") { - const double width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.0; - const double dx=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*0.25; - const double ypos=y-JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()/2.0; - const QPainterPath path=JKQTMathTextMakeArrow(x+shift+dx, ypos, width, JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height()*0.5, true, false); - } else if (symbolName=="longrightarrow"){ - const double width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.0; - const double dx=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*0.25; - const double ypos=y-JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()/2.0; - const QPainterPath path=JKQTMathTextMakeArrow(x+shift+dx, ypos, width, JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height()*0.5, false, true); - painter.drawPath(path); - } else if (symbolName=="Longleftarrow") { - const double width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.0; - const double dx=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*0.25; - const double ypos=y-JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()/2.0; - const QPainterPath path=JKQTMathTextMakeDArrow(x+shift+dx, ypos, width, JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height()*0.5, true, false); - } else if (symbolName=="Longrightarrow") { - const double width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.0; - const double dx=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*0.25; - const double ypos=y-JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()/2.0; - const QPainterPath path=JKQTMathTextMakeDArrow(x+shift+dx, ypos, width, JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height()*0.5, false, true); - painter.drawPath(path); - } else if (symbolName=="longleftrightarrow") { - const double width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.0; - const double dx=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*0.25; - const double ypos=y-JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()/2.0; - const QPainterPath path=JKQTMathTextMakeArrow(x+shift+dx, ypos, width, JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height()*0.5, true, true); - painter.drawPath(path); - } else if (symbolName=="Longleftrightarrow") { - const double width=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*3.0; - const double dx=JKQTMathTextGetTightBoundingRect(f, "X", painter.device()).width()*0.25; - const double ypos=y-JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()/2.0; - const QPainterPath path=JKQTMathTextMakeDArrow(x+shift+dx, ypos, width, JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height()*0.5, true, true); - painter.drawPath(path); + if (has(symflags, DrawSlash)) { + painter.drawText(QPointF(0,0),"/"); + } + /*painter.save(); + painter.setPen(QPen(QColor("red"), 0.5, Qt::DotLine)); + painter.drawEllipse(0,0,5,5); + painter.drawRect(tbr); + painter.setPen(QPen(QColor("blue"), 0.5, Qt::DashLine)); + painter.drawRect(br); + painter.restore();*/ } else { // draw a box to indicate an unavailable symbol - const QRectF tbr=JKQTMathTextGetTightBoundingRect(f, "M", painter.device()); - painter.drawRect(QRectF(x+shift,y-tbr.height(), xwi, tbr.height()*0.8)); + painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); + painter.setPen(QPen(currentEv.color, fm.lineWidth())); + painter.drawRect(QRectF(x0.x(), x0.y()-tbrNoSymbol.height(), tbrNoSymbol.width(), tbrNoSymbol.height())); } - painter.setPen(pold); - painter.setFont(fold); + return x+width; } bool JKQTMathTextSymbolNode::toHtml(QString &html, JKQTMathTextEnvironment currentEv, JKQTMathTextEnvironment defaultEv) { bool ok=true; - QString s; + const auto props=symbols.value(symbolName, SymbolFullProps()); + QString s=props.html.symbol; JKQTMathTextEnvironment ev=currentEv; - - static QMap entitylut; - if (entitylut.isEmpty()) { - entitylut.insert("sin", "sin"); - entitylut.insert("cos", "cos"); - entitylut.insert("tan", "tan"); - entitylut.insert("sinh", "sinh"); - entitylut.insert("cosh", "cosh"); - entitylut.insert("tanh", "tanh"); - entitylut.insert("atan", "atan"); - entitylut.insert("acos", "acos"); - entitylut.insert("asin", "asin"); - entitylut.insert("arcsin", "arcsin"); - entitylut.insert("arccos", "arccos"); - entitylut.insert("arctan", "arctan"); - entitylut.insert("ii", "i"); - entitylut.insert("dd", "d"); - entitylut.insert("exp", "exp"); - entitylut.insert("log", "log"); - entitylut.insert("ln", "ln"); - entitylut.insert("ld", "ld"); - entitylut.insert("lb", "lb"); - entitylut.insert("erf", "erf"); - entitylut.insert("mod", "mod"); - entitylut.insert("median", "median"); - entitylut.insert("min", "min"); - entitylut.insert("max", "max"); - entitylut.insert("argmin", "argmin"); - entitylut.insert("argmax", "argmax"); - entitylut.insert("inf", "inf"); - entitylut.insert("sup", "sup"); - entitylut.insert("liminf", "liminf"); - entitylut.insert("limsup", "limsup"); - entitylut.insert("lim", "lim"); - entitylut.insert("sec", "sec"); - entitylut.insert("gcd", "gcd"); - entitylut.insert("hom", "hom"); - entitylut.insert("ker", "ker"); - entitylut.insert("dim", "dim"); - entitylut.insert("cot", "cot"); - entitylut.insert("arg", "arg"); - entitylut.insert("det", "det"); - entitylut.insert("deg", "deg"); - entitylut.insert("sign", "sign"); - entitylut.insert("sgn", "sgn"); - entitylut.insert("Pr", "Pr"); - entitylut.insert("coth", "coth"); - entitylut.insert("alpha", "α"); - entitylut.insert("beta", "β"); - entitylut.insert("gamma", "γ"); - entitylut.insert("delta", "δ"); - entitylut.insert("epsilon", "ε"); - entitylut.insert("varepsilon", "ε"); - entitylut.insert("zeta", "ζ"); - entitylut.insert("eta", "η"); - entitylut.insert("theta", "θ"); - entitylut.insert("vartheta", "ϑ"); - entitylut.insert("iota", "ι"); - entitylut.insert("kappa", "κ"); - entitylut.insert("lambda", "λ"); - entitylut.insert("mu", "μ"); - entitylut.insert("nu", "ν"); - entitylut.insert("xi", "ξ"); - entitylut.insert("pi", "π"); - entitylut.insert("varpi", "ϖ"); - entitylut.insert("rho", "ρ"); - entitylut.insert("sigma", "σ"); - entitylut.insert("varsigma", "ς"); - entitylut.insert("tau", "τ"); - entitylut.insert("upsilon", "υ"); - entitylut.insert("phi", "φ"); - entitylut.insert("varphi", "φ"); - entitylut.insert("chi", "χ"); - entitylut.insert("psi", "ψ"); - entitylut.insert("omega", "ω"); - entitylut.insert("Gamma", "Γ"); - entitylut.insert("Delta", "Δ"); - entitylut.insert("Theta", "Θ"); - entitylut.insert("Lambda", "Λ"); - entitylut.insert("Omega", "Ω"); - entitylut.insert("Xi", "Ξ"); - entitylut.insert("Pi", "Π"); - entitylut.insert("Sigma", "Σ"); - entitylut.insert("Upsilon", "Υ"); - entitylut.insert("Phi", "Φ"); - entitylut.insert("Psi", "Ψ"); - entitylut.insert("leftrightarrow", "↔"); - entitylut.insert("leftarrow", "←"); - entitylut.insert("rightarrow", "→"); - entitylut.insert("to", "→"); - entitylut.insert("uparrow", "↑"); - entitylut.insert("downarrow", "↓"); - entitylut.insert("Leftrightarrow", "⇔"); - entitylut.insert("iff", "⇔"); - entitylut.insert("Leftarrow", "⇐"); - entitylut.insert("Rightarrow", "⇒"); - entitylut.insert("Uparrow", "⇑"); - entitylut.insert("Downarrow", "⇓"); - entitylut.insert("pm", "±"); - entitylut.insert("leq", "≤"); - entitylut.insert("geq", "≥"); - entitylut.insert("times", "×"); - 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", "≡"); - entitylut.insert("approx", "≈"); - entitylut.insert("ellipsis", "..."); - entitylut.insert("Im", "ℑ"); - entitylut.insert("Re", "ℜ"); - entitylut.insert("otimes", "⊗"); - entitylut.insert("oplus", "⊕"); - entitylut.insert("oslash", "/"); - entitylut.insert("cap", "∩"); - entitylut.insert("cup", "∪"); - entitylut.insert("land", "∩"); - entitylut.insert("lor", "∪"); - entitylut.insert("supset", "⊃"); - entitylut.insert("supseteq", "⊇"); - entitylut.insert("supsetnot", "⊅"); - entitylut.insert("subset", "⊂"); - entitylut.insert("subseteq", "⊆"); - entitylut.insert("in", "∈"); - entitylut.insert("notin", "∉"); - entitylut.insert("angle", "∠"); - entitylut.insert("nabla", "∇"); - entitylut.insert("copyright", "©"); - entitylut.insert("registered", "®"); - entitylut.insert("trademark", "™"); - entitylut.insert("textregistered", "™"); - entitylut.insert("cdot", "⋅"); - entitylut.insert("neg", "¬"); - entitylut.insert("wedge", "∧"); - entitylut.insert("vee", "∨"); - entitylut.insert("diamond", "◊"); - entitylut.insert("langle", "⟨"); - entitylut.insert("rangle", "⟩"); - entitylut.insert("int", "∫"); - entitylut.insert("forall", "∀"); - entitylut.insert("exists", "∃"); - entitylut.insert("cong", "∼"); - entitylut.insert("bot", "⊥"); - entitylut.insert("llcorner", "⌜"); - entitylut.insert("lrcorner", "⌝"); - entitylut.insert("ulcorner", "⌜"); - entitylut.insert("urcorner", "⌝"); - entitylut.insert("blcorner", "⌞"); - entitylut.insert("brcorner", "⌞"); - entitylut.insert("tlcorner", "⌟"); - entitylut.insert("trcorner", "⌟"); - - - entitylut.insert("ll", "<<"); - entitylut.insert("gg", ">>"); - entitylut.insert("bbC", "C"); - entitylut.insert("bbH", "H"); - entitylut.insert("bbN", "N"); - entitylut.insert("bbP", "P"); - entitylut.insert("bbQ", "Q"); - entitylut.insert("bbR", "R"); - entitylut.insert("bbZ", "Z"); - entitylut.insert("Alef", "ℵ"); - entitylut.insert("alef", "ℵ"); - entitylut.insert("tilde", "~"); - entitylut.insert("iint", "∫∫"); - entitylut.insert("iiint", "∫∫∫"); - entitylut.insert("emptyset", "∅"); - entitylut.insert("varnothing", "∅"); - entitylut.insert("lceil", "⌈"); - entitylut.insert("rceil", "⌉"); - entitylut.insert("lfloor", "⌊"); - entitylut.insert("rfloor", "⌋"); - entitylut.insert("subsetnot", "⊄"); - entitylut.insert("DC", "="); - entitylut.insert("cdots", "⋅⋅⋅"); - entitylut.insert("dots", "..."); - entitylut.insert("ldots", "..."); - - entitylut.insert("cent", "¢"); - - entitylut.insert("_", "_"); - entitylut.insert("}", "}"); - entitylut.insert("{", "{"); - entitylut.insert("hbar", "ℏ"); - entitylut.insert("euro", "€"); - entitylut.insert("pound", "£"); - entitylut.insert("yen", "¥"); - entitylut.insert("div", "÷"); - entitylut.insert("backslash", "\\"); - entitylut.insert("$", "$"); - entitylut.insert("%", "%"); - entitylut.insert("&", "&"); - entitylut.insert("#", "#"); - entitylut.insert("|", "||"); - entitylut.insert("<", "<"); - entitylut.insert(">", ">"); - entitylut.insert("ast", "*"); - entitylut.insert("glq", "‘"); - entitylut.insert("grq", "’"); - entitylut.insert("glqq", "“"); - entitylut.insert("grqq", "”"); - entitylut.insert("flq", "‹"); - entitylut.insert("frq", "›"); - entitylut.insert("flqq", "«"); - entitylut.insert("frqq", "»"); - entitylut.insert("prime", "′"); - entitylut.insert("dprime", "″"); - entitylut.insert("trprime", "‴"); - } - - - QMap::iterator itS = entitylut.find(symbolName); - if (itS!=entitylut.end()) { s=itS.value(); } - else if (symbolName == "sum") { - ev.fontSize*=parentMathText->getBigMathoperatorFontFactor(); s="∑"; } - else if (symbolName == "prod") { - ev.fontSize*=parentMathText->getBigMathoperatorFontFactor(); s="∏"; } - else if (symbolName == "bigcap") { ev.fontSize*=parentMathText->getBigMathoperatorFontFactor(); s="∩"; } - else if (symbolName == "bigcup") { ev.fontSize*=parentMathText->getBigMathoperatorFontFactor(); s="∪"; } - else if (symbolName == "bigvee") { ev.fontSize*=parentMathText->getBigMathoperatorFontFactor(); s="∨"; } - else if (symbolName == "bighat") { ev.fontSize*=parentMathText->getBigMathoperatorFontFactor(); s="∧"; } - else ok=false; - + ev.fontSize=ev.fontSize*props.html.fontScalingFactor; + if (has(props.globalFlags, ExtendWidthInMathmode)) s=" "+s+" "; + if (has(props.globalFlags, MakeWhitespaceHalf)) s.replace(" ", " "); if (ok) html=html+ev.toHtmlStart(defaultEv)+s+ev.toHtmlAfter(defaultEv); return ok; } @@ -1316,12 +242,6 @@ QString JKQTMathTextSymbolNode::getSymbolName() const { return this->symbolName; } -QString JKQTMathTextSymbolNode::getSymbolfontName() const { - JKQTMathTextEnvironment currentEv; - auto props=getSymbolProp(symbolName, currentEv); - return props.font; -} - bool JKQTMathTextSymbolNode::getAddWhitespace() const { return addWhitespace; @@ -1339,4 +259,717 @@ void JKQTMathTextSymbolNode::getSymbolSize(QPainter &painter, JKQTMathTextEnviro } +bool JKQTMathTextSymbolNode::hasSymbol(const QString &symbolName) +{ + fillSymbolTables(); + return symbols.contains(symbolName); +} + + +JKQTMathTextSymbolNode::SymbolProps::SymbolProps(): + SymbolProps(QString()) +{ + +} + +JKQTMathTextSymbolNode::SymbolProps::SymbolProps(const QString &_symbol, SymbolFlags _flags, double _fontScalingFactor, double _yShiftFactor): + symbol(_symbol), + flags(_flags), + fontScalingFactor(_fontScalingFactor), + yShiftFactor(_yShiftFactor) +{ +} + + +JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::MathOperatorSymbol(const QString &op) +{ + return MathOperatorSymbol(op, op); +} + +JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::MathOperatorSymbol(const QString &op, const QString &ophtml) +{ + return SymbolFullProps(SymbolProps(op, ItalicOff|BoldOff, 1.0, 0.0)).setGlobalFlags(ExtendWidthInMathmode).addHtml(ophtml, ItalicOff|BoldOff, 1.0, 0.0); +} + +JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::MathOperatorText(const QString &op) +{ + return MathOperatorText(op, op); +} + +JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::MathOperatorText(const QString &op, const QString &ophtml) +{ + return SymbolFullProps(SymbolProps(op, ItalicOff|BoldOff|HeightIsAscent, 1.0, 0.0)).setGlobalFlags(ExtendWidthInMathmode|MakeWhitespaceHalf).addHtml(ophtml, ItalicOff|BoldOff|HeightIsAscent, 1.0, 0.0); +} + +JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::MathOperatorSymbolUnicode(const QString &unicode) +{ + return SymbolFullProps(MTFEUnicode, SymbolProps(unicode, ItalicOff|BoldOff, 1.0, 0.0)).setGlobalFlags(ExtendWidthInMathmode|MakeWhitespaceHalf); +} + +JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::GreekLetter_WinSymbol_Unicode_Html(const QString &letterWinSymbol, const QString &letterUnicode, const QString &html) +{ + return SymbolFullProps(MTEFallbackGreek, MTFEUnicode, SymbolProps(letterUnicode), MTFEWinSymbol, SymbolProps(letterWinSymbol), html); +} + +JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::SymbolStd(const QString &symbol, const QString &html) +{ + return SymbolFullProps(MTFEStandard, SymbolProps(symbol), html); +} + +JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::SymbolUnicode(const QString &symbol, const QString &html) +{ + return SymbolFullProps(MTFEUnicode, SymbolProps(symbol), html); +} + +JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::UprightSymbolStd(const QString &symbol, const QString &html) +{ + return SymbolFullProps(MTFEStandard, SymbolProps(symbol, ItalicOff), html, ItalicOff); +} + +JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::UprightSymbolUnicode(const QString &symbol, const QString &html) +{ + return SymbolFullProps(MTFEUnicode, SymbolProps(symbol, ItalicOff), html, ItalicOff); +} + +JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::SimpleTextSymbol(const QString &symbol, const QString &html) +{ + return SymbolFullProps(MTFEStandard, SymbolProps(symbol), html); +} + +JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::SimpleTextSymbol(const QString &symbol) +{ + return SymbolFullProps(MTFEStandard, SymbolProps(symbol), symbol); +} + +JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::SimpleUprightTextSymbol(const QString &symbol, const QString &html) +{ + return SymbolFullProps(MTFEStandard, SymbolProps(symbol, ItalicOff), html, ItalicOff); +} + +JKQTMathTextSymbolNode::SymbolFullProps JKQTMathTextSymbolNode::SimpleUprightTextSymbol(const QString &symbol) +{ + return SymbolFullProps(MTFEStandard, SymbolProps(symbol, ItalicOff), symbol, ItalicOff); +} + + + +QHash JKQTMathTextSymbolNode::symbols=QHash(); + +void JKQTMathTextSymbolNode::fillSymbolTables() +{ + if (symbols.size()>0) return; // tables have already been filled! So nothing to do here + + /************************************************************************************** + * STANDARD Symbols available in all standard fonts + **************************************************************************************/ + symbols[" "]=SimpleTextSymbol(" ", " "); + symbols[""]=SimpleTextSymbol(" ", " "); + symbols["#"]=SimpleTextSymbol("#", "#"); + symbols["%"]=SimpleTextSymbol("%", "≫"); + symbols["&"]=SimpleTextSymbol("&", "&"); + symbols["("]=SimpleUprightTextSymbol("("); + symbols[")"]=SimpleUprightTextSymbol(")"); + symbols["["]=SimpleUprightTextSymbol("["); + symbols["]"]=SimpleUprightTextSymbol("]"); + symbols["_"]=SimpleTextSymbol("_"); + symbols["{"]=SimpleUprightTextSymbol("{"); + symbols["|"]=SimpleUprightTextSymbol("||", "‖").addUprightUnicode(QChar(0x2016)); + symbols["}"]=SimpleUprightTextSymbol("}"); + symbols["AC"]=UprightSymbolUnicode(QChar(0x223F)).addUprightHtml("∿").addUprightStd("~"); + symbols["Angstrom"]= symbols["Angstroem"]=UprightSymbolUnicode(QChar(0x212B)).addUprightStd(QChar(0xC5)); + symbols["Beth"]=symbols["Bet"]=symbols["beth"]=symbols["bet"]=SymbolUnicode(QChar(0x2136)).addHtml("ℶ"); + symbols["Box"]=UprightSymbolUnicode(QChar(0x25A1)); + symbols["DC"]=SymbolUnicode(QChar(0x2393)).addWinSymbol(QChar(0xBB)).addStd("="); + symbols["EUR"]=SymbolUnicode(QChar(0x20AC)); + symbols["Im"]=UprightSymbolUnicode(QChar(0x2111)).addHtml("ℑ").addWinSymbol(QChar(0xC1)); + symbols["No"]=SymbolUnicode(QChar(0x2116)); + symbols["Ohm"]=symbols["ohm"]=UprightSymbolUnicode(QChar(0x2126)).addUprightWinSymbol("W").addUprightHtml("Ω"); + symbols["P"]=SimpleTextSymbol(QChar(0xB6)).addHtml("¶"); + symbols["Re"]=SymbolUnicode(QChar(0x211C)).addHtml("ℜ").addWinSymbol(QChar(0xC2)); + symbols["S"]=symbols["§"]=SimpleTextSymbol(QChar(0xA7)).addHtml("§"); + symbols["accurrent"]=SymbolUnicode(QChar(0x23E6)); + symbols["alef"]=symbols["aleph"]=symbols["Aleph"]=symbols["Alef"]=SymbolUnicode(QChar(0x2135)).addHtml("ℵ").addWinSymbol(QChar(0xC0)); + symbols["angle"]=UprightSymbolUnicode(QChar(0x2220)).addHtml("∠").addWinSymbol(QChar(0xD0)); + symbols["backslash"]=SimpleTextSymbol("\\"); + symbols["benzene"]=UprightSymbolUnicode(QChar(0x232C)); + symbols["benzenr"]=UprightSymbolUnicode(QChar(0x23E3)); + symbols["blacksquare"]=UprightSymbolUnicode(QChar(0x220E)).addHtml("□"); + symbols["blcorner"]=symbols["llcorner"]=UprightSymbolUnicode(QChar(0x231E)); + symbols["brcorner"]=symbols["lrcorner"]=UprightSymbolUnicode(QChar(0x231F)); + symbols["bullet"]=UprightSymbolUnicode(QChar(0x2022)).addUprightHtml("•").addUprightWinSymbol(QChar(0xB7)); + symbols["cdots"]=SymbolUnicode(QChar(0x22EF)).addHtml("···").addStd(QString(3, QChar(0xB7))); + symbols["celsius"]=symbols["degC"]=SymbolUnicode(QChar(0x2103)).addUprightStd("°C").addUprightHtml("°C"); + symbols["cent"]=SimpleTextSymbol(QChar(0xA2), "¢"); + symbols["circ"]=UprightSymbolStd(QChar(0x2218)); + symbols["co"]=UprightSymbolUnicode(QChar(0x2105)); + symbols["copyright"]=symbols["textcopyright"]=SimpleTextSymbol(QChar(0xA5), "©"); + symbols["dalet"]=symbols["Dalet"]=symbols["daleth"]=symbols["Daleth"]=SymbolUnicode(QChar(0x2138)).addHtml("ℸ"); + symbols["dd"] = SymbolFullProps(SymbolProps("d", Upright|BoldOff), "d", Upright|BoldOff); + symbols["diamond"]=UprightSymbolUnicode(QChar(0x22C4)).addHtml("⋄").addWinSymbol(QChar(0xE0)); + symbols["dollar"]=SymbolUnicode(QChar(0x0024)); + symbols["dollar"]=symbols["$"]=SimpleTextSymbol(QChar(0x24), "$"); + symbols["dprime"]=SymbolUnicode(QChar(0x2033)).addHtml("″").addStd("''"); + symbols["ellipsis"]=symbols["dots"]=symbols["ldots"]=SymbolUnicode(QChar(0x2026)).addHtml("…").addWinSymbol(QChar(0xBC)).addStd("..."); + symbols["euro"]=symbols["EUR"]=SimpleTextSymbol(QChar(0x20AC), "€"); + symbols["fahrenheit"]=symbols["degF"]=SymbolUnicode(QChar(0x2109)); + symbols["female"]=SymbolUnicode(QChar(0x2640)).addHtml("♀"); + symbols["flq"]=SymbolUnicode(QChar(0x2039)).addHtml("‹").addStd("<"); + symbols["flqq"]=SymbolUnicode(QChar(0x00AB)).addHtml("«").addStd(QChar(0xAB)); + symbols["frown"]=SymbolUnicode(QChar(0x2322)).addHtml("⌢"); + symbols["frq"]=SymbolUnicode(QChar(0x203A)).addHtml("›").addStd(">"); + symbols["frqq"]=SymbolUnicode(QChar(0x00BB)).addHtml("»").addStd(QChar(0xBB)); + symbols["gimel"]=symbols["Gimel"]=SymbolUnicode(QChar(0x2137)).addHtml("ℷ"); + symbols["glq"]=SymbolUnicode(QChar(0x2018)).addHtml("‘").addStd("'"); + symbols["glqq"]=SymbolUnicode(QChar(0x201C)).addHtml("“").addStd("\""); + symbols["grq"]=SymbolUnicode(QChar(0x2019)).addHtml("’").addStd("'"); + symbols["grqq"]=SymbolUnicode(QChar(0x201D)).addHtml("”").addStd("\""); + symbols["hbar"]=SymbolUnicode(QChar(0x210F)).addHtml("ℏ").addStd("h", DrawBar); + symbols["hexagon"]=UprightSymbolUnicode(QChar(0x2394)); + symbols["ii"] = SymbolFullProps(SymbolProps("i", Upright|BoldOff), "i", Upright|BoldOff); + symbols["infty"]=SymbolUnicode(QChar(0x221E)).addHtml("∞").addWinSymbol(QChar(0xA5)).addStd("8", Rotate90); + symbols["langle"]=UprightSymbolUnicode(QChar(0x2329)).addWinSymbol(QChar(0xE1)); + symbols["lceil"]=UprightSymbolUnicode(QChar(0x2308)).addHtml("⌈").addWinSymbol(QChar(0xE9)); + symbols["ldots"]=symbols["dots"]=SimpleTextSymbol("..."); + symbols["lfloor"]=UprightSymbolUnicode(QChar(0x230A)).addHtml("⌊").addWinSymbol(QChar(0xEB)); + symbols["lightning"]=SymbolUnicode(QChar(0x21AF)); + symbols["male"]=SymbolUnicode(QChar(0x2642)).addHtml("♂"); + symbols["measuredangle"]=UprightSymbolUnicode(QChar(0x2221)).addHtml("∡"); + symbols["micro"] = SimpleTextSymbol(QChar(0xB5), "µ"); + symbols["ohm"]=SymbolUnicode(QChar(0x2126)); + symbols["partial"]=UprightSymbolUnicode(QChar(0x2202)).addHtml("∂").addWinSymbol(QChar(0xB6)); + symbols["perthousand"]=symbols["permil"]=SymbolUnicode(QChar(0x2030)).addHtml("‰"); + symbols["pound"]=SimpleTextSymbol(QChar(0xA3), "£"); + symbols["pound"]=SymbolUnicode(QChar(0x00A3)); + symbols["prime"]=SymbolUnicode(QChar(0x2032)).addHtml("′").addStd("'"); + symbols["rangle"]=UprightSymbolUnicode(QChar(0x232A)).addWinSymbol(QChar(0xF1)); + symbols["rceil"]=UprightSymbolUnicode(QChar(0x2309)).addHtml("⌉").addWinSymbol(QChar(0xF9)); + symbols["registered"]=symbols["textregistered"]=symbols["circledR"]=SimpleTextSymbol(QChar(0xAA), "®"); + symbols["rfloor"]=UprightSymbolUnicode(QChar(0x230B)).addHtml("⌋").addWinSymbol(QChar(0xFB)); + symbols["rightangle"]=UprightSymbolUnicode(QChar(0x221F)).addHtml("∟"); + symbols["smile"]=UprightSymbolUnicode(QChar(0x2323)).addHtml("⌣"); + symbols["sphericalangle"]=UprightSymbolUnicode(QChar(0x2222)).addHtml("∢"); + symbols["star"]=UprightSymbolUnicode(QChar(0x22C6)); + symbols["tcohm"]=SymbolUnicode(QChar(0x2126)); + symbols["textbar"]=SimpleTextSymbol("|", "|"); + symbols["textdegree"]=symbols["degree"] = SimpleTextSymbol(QChar(0xB0), "°"); + symbols["textgreater"]=SimpleTextSymbol(">", ">"); + symbols["textless"]=SimpleTextSymbol("<", "<"); + symbols["tlcorner"]=symbols["ulcorner"]=SymbolUnicode(QChar(0x231C)); + symbols["trademark"]=SymbolUnicode(QChar(0x2122)).addHtml("™").addWinSymbol(QChar(0xD4)).addStd("(TM)"); + symbols["trapezium"]=SymbolUnicode(QChar(0x23E2)).addHtml("⏢"); + symbols["trcorner"]=symbols["urcorner"]=UprightSymbolUnicode(QChar(0x231D)); + symbols["trprime"]=SymbolUnicode(QChar(0x2034)).addHtml("‴").addStd("'''"); + symbols["varcarriagereturn"]=SymbolUnicode(QChar(0x23CE)).addWinSymbol(QChar(0xBF)); + symbols["varhexagonlrbonds"]=SymbolUnicode(QChar(0x232C)); + symbols["yen"]=SimpleTextSymbol(QChar(0xA5), "¥"); + symbols["yen"]=SymbolUnicode(QChar(0x00A5)); + + + + + + /************************************************************************************** + * STANDARD MathOperator Strings + **************************************************************************************/ + symbols["Pr"] = MathOperatorText("Pr"); + symbols["acos"] = MathOperatorText("acos"); + symbols["arccos"] = MathOperatorText("arccos"); + symbols["arcsin"] = MathOperatorText("arcsin"); + symbols["arctan"] = MathOperatorText("arctan"); + symbols["arg"] = MathOperatorText("arg"); + symbols["argmax"] = MathOperatorText("arg max", "arg max"); + symbols["argmin"] = MathOperatorText("arg min", "arg min"); + symbols["asin"] = MathOperatorText("asin"); + symbols["atan"] = MathOperatorText("atan"); + symbols["cos"] = MathOperatorText("cos"); + symbols["cosh"] = MathOperatorText("cosh"); + symbols["cot"] = MathOperatorText("cot"); + symbols["coth"] = MathOperatorText("coth"); + symbols["coth"] = MathOperatorText("coth"); + symbols["deg"] = MathOperatorText("deg"); + symbols["det"] = MathOperatorText("det"); + symbols["dim"] = MathOperatorText("dim"); + symbols["exp"] = MathOperatorText("exp"); + symbols["gcd"] = MathOperatorText("gcd"); + symbols["hom"] = MathOperatorText("hom"); + symbols["ker"] = MathOperatorText("ker"); + symbols["lb"] = MathOperatorText("lb"); + symbols["ld"] = MathOperatorText("ld"); + symbols["lim"] = MathOperatorText("lim"); + symbols["liminf"] = MathOperatorText("lim inf", "lim inf"); + symbols["limsup"] = MathOperatorText("lim sup", "lim sup"); + symbols["ln"] = MathOperatorText("ln"); + symbols["log"] = MathOperatorText("log"); + symbols["max"] = MathOperatorText("max"); + symbols["median"] = MathOperatorText("median"); + symbols["min"] = MathOperatorText("min"); + symbols["mod"] = MathOperatorText("mod"); + symbols["sec"] = MathOperatorText("sec"); + symbols["sgn"] = MathOperatorText("sgn"); + symbols["sign"] = MathOperatorText("sign"); + symbols["sin"] = MathOperatorText("sin"); + symbols["sinh"] = MathOperatorText("sinh"); + symbols["tan"] = MathOperatorText("tan"); + symbols["tanh"] = MathOperatorText("tanh"); + + /************************************************************************************** + * STANDARD MathOperator Symbols + **************************************************************************************/ + symbols["*"]=symbols["ast"]=symbols["asterisk"]=MathOperatorSymbolUnicode(QChar(0x2217)).addMathOperatorStd("*").addMathOperatorHtml("*"); + symbols["+"]=MathOperatorSymbolUnicode(QChar(0x2B)).addMathOperatorHtml("+").addMathOperatorStd("+"); + symbols["-"]=MathOperatorSymbolUnicode(QChar(0x2212)).addMathOperatorHtml("-").addMathOperatorStd("-"); + symbols["<"]=MathOperatorSymbol("<", "<"); + symbols["="] = MathOperatorSymbol("="); + symbols[">"]=MathOperatorSymbol(">", ">"); + symbols["Downarrow"]=UprightSymbolUnicode(QChar(0x21D3)).addUprightHtml("⇓").addUprightWinSymbol(QChar(0xDF)); + symbols["Leftarrow"]=UprightSymbolUnicode(QChar(0x21D0)).addUprightHtml("⇐").addUprightWinSymbol(QChar(0xDC)); + symbols["Rightarrow"]=UprightSymbolUnicode(QChar(0x21D2)).addUprightHtml("⇒").addUprightWinSymbol(QChar(0xDE)); + symbols["Uparrow"]=UprightSymbolUnicode(QChar(0x21D1)).addUprightHtml("⇑").addUprightWinSymbol(QChar(0xDD)); + symbols["Updownarrow"]=UprightSymbolUnicode(QChar(0x21D5)).addUprightHtml("⇕"); + symbols["approx"]=MathOperatorSymbolUnicode(QChar(0x2248)).addMathOperatorHtml("≈").addMathOperatorWinSymbol(QChar(0xBB)); + symbols["bbC"]=SymbolUnicode(QChar(0x2102)); + symbols["bbH"]=MathOperatorSymbolUnicode(QChar(0x210D)); + symbols["bbN"]=MathOperatorSymbolUnicode(QChar(0x2115)); + symbols["bbP"]=MathOperatorSymbolUnicode(QChar(0x2119)); + symbols["bbQ"]=MathOperatorSymbolUnicode(QChar(0x211A)); + symbols["bbR"]=MathOperatorSymbolUnicode(QChar(0x211D)); + symbols["bbZ"]=MathOperatorSymbolUnicode(QChar(0x2124)); + symbols["because"]=MathOperatorSymbolUnicode(QChar(0x2235)).addMathOperatorHtml("∵"); + symbols["bigcap"]=MathOperatorSymbolUnicode(QChar(0x22C2)).addMathOperatorHtml("∫").addMathOperatorWinSymbol(QChar(0xC7), 1.8); + symbols["bigcup"]=MathOperatorSymbolUnicode(QChar(0x22C3)).addMathOperatorHtml("∫").addMathOperatorWinSymbol(QChar(0xC8), 1.8); + symbols["bighat"]=MathOperatorSymbolUnicode(QChar(0x22C0)).addMathOperatorHtml("∫").addMathOperatorWinSymbol(QChar(0xD9), 1.8); + symbols["bigvee"]=MathOperatorSymbolUnicode(QChar(0x22C1)).addMathOperatorHtml("∫").addMathOperatorWinSymbol(QChar(0xDA), 1.8); + symbols["bot"]=symbols["perp"]=MathOperatorSymbolUnicode(QChar(0x22A5)).addMathOperatorHtml("⊥"); + symbols["cap"]=symbols["land"]=MathOperatorSymbolUnicode(QChar(0x2229)).addMathOperatorHtml("∩").addMathOperatorWinSymbol(QChar(0xC7)); + symbols["cdot"]=MathOperatorSymbol(QChar(0xB7)).addMathOperatorHtml("·").addMathOperatorWinSymbol(QChar(0xD7)); + symbols["cong"]=MathOperatorSymbolUnicode(QChar(0x2245)).addMathOperatorHtml("≅"); + symbols["coprod"]=MathOperatorSymbolUnicode(QChar(0x2210)).addMathOperatorHtml("∐").addWinSymbol(QChar(0xD5), ItalicOff|BoldOff|FlipUpDown, 1.8, 0.1); + symbols["cup"]=symbols["lor"]=MathOperatorSymbolUnicode(QChar(0x222A)).addMathOperatorHtml("∪").addMathOperatorWinSymbol(QChar(0xC8)); + symbols["ddots"]=MathOperatorSymbolUnicode(QChar(0x22F1)).addMathOperatorHtml("⋱"); + symbols["div"]=MathOperatorSymbolUnicode(QChar(0x00F7)).addMathOperatorHtml("÷").addMathOperatorWinSymbol(QChar(0xB8)); + symbols["downarrow"]=UprightSymbolUnicode(QChar(0x2193)).addUprightHtml("↓").addUprightWinSymbol(QChar(0xAF)); + symbols["downharpoonleft"]=UprightSymbolUnicode(QChar(0x21C3)).addUprightHtml("⇃"); + symbols["downharpoonright"]=UprightSymbolUnicode(QChar(0x21C2)).addUprightHtml("⇂"); + symbols["emptyset"]=symbols["varnothing"]=MathOperatorSymbolUnicode(QChar(0x2205)).addMathOperatorHtml("∅").addMathOperatorWinSymbol(QChar(0xC6)).addStd("0", BoldOff|ItalicOff|DrawSlash); + symbols["equiv"]=MathOperatorSymbolUnicode(QChar(0x2261)).addMathOperatorHtml("≡").addMathOperatorWinSymbol(QChar(0xBA)); + symbols["exists"]=MathOperatorSymbolUnicode(QChar(0x2203)).addMathOperatorHtml("∃").addMathOperatorWinSymbol(QChar(0x24)).addStd("E", ItalicOff|BoldOff|FlipLeftRight); + symbols["forall"]=MathOperatorSymbolUnicode(QChar(0x2200)).addMathOperatorHtml("∀").addMathOperatorWinSymbol(QChar(0x22)).addStd("A", ItalicOff|BoldOff|FlipUpDown); + symbols["geq"]=symbols["ge"]=MathOperatorSymbolUnicode(QChar(0x2265)).addMathOperatorHtml("≥").addMathOperatorWinSymbol(QChar(0xB3)); + symbols["geqq"]=MathOperatorSymbolUnicode(QChar(0x2267)).addMathOperatorHtml("≧"); + symbols["gg"]=MathOperatorSymbolUnicode(QChar(0x226B)).addMathOperatorHtml("≫").addMathOperatorStd(">>"); + symbols["iddots"]=MathOperatorSymbolUnicode(QChar(0x22F0)).addMathOperatorHtml("⋰"); + symbols["iff"]=symbols["Leftrightarrow"]=UprightSymbolUnicode(QChar(0x21D4)).addUprightHtml("⇔").addUprightWinSymbol(QChar(0xDB)); + symbols["iiint"]=MathOperatorSymbolUnicode(QChar(0x222D)).setGlobalFlags(IntLikeSymbolCorrection).addMathOperatorHtml("∭").addMathOperatorWinSymbol(QString(3, QChar(0xF2)), 1.8, 0.1); + symbols["iint"]=MathOperatorSymbolUnicode(QChar(0x222C)).setGlobalFlags(IntLikeSymbolCorrection).addMathOperatorHtml("∬").addMathOperatorWinSymbol(QString(2, QChar(0xF2)), 1.8, 0.1); + symbols["in"]=MathOperatorSymbolUnicode(QChar(0x2208)).addMathOperatorHtml("∈").addMathOperatorWinSymbol(QChar(0xCE)); + symbols["int"]=MathOperatorSymbolUnicode(QChar(0x222B)).setGlobalFlags(IntLikeSymbolCorrection).addMathOperatorHtml("∫").addMathOperatorWinSymbol(QChar(0xF2), 1.8, 0.1); + symbols["leftarrow"]=UprightSymbolUnicode(QChar(0x2190)).addUprightHtml("←").addUprightWinSymbol(QChar(0xAC)); + symbols["leftharpoondown"]=UprightSymbolUnicode(QChar(0x21BD)).addUprightHtml("↽"); + symbols["leftharpoonup"]=UprightSymbolUnicode(QChar(0x21BC)).addUprightHtml("↼"); + symbols["leftrightarrow"]=UprightSymbolUnicode(QChar(0x2194)).addUprightHtml("↔").addUprightWinSymbol(QChar(0xAB)); + symbols["leftrightharpoon"]=UprightSymbolUnicode(QChar(0x21CB)).addUprightHtml("⇋"); + symbols["leq"]=symbols["le"]=MathOperatorSymbolUnicode(QChar(0x2264)).addMathOperatorHtml("≤").addMathOperatorWinSymbol(QChar(0xA3)); + symbols["leqq"]=MathOperatorSymbolUnicode(QChar(0x2266)).addMathOperatorHtml("≦"); + symbols["ll"]=MathOperatorSymbolUnicode(QChar(0x226A)).addMathOperatorHtml("≪").addMathOperatorStd("<<"); + symbols["lnot"]=MathOperatorSymbolUnicode(QChar(0xAC)).addMathOperatorWinSymbol(QChar(0xD8)).addMathOperatorHtml("¬"); + symbols["mapimage"]=MathOperatorSymbolUnicode(QChar(0x22B7)).addMathOperatorHtml("⊷"); + symbols["maporiginal"]=MathOperatorSymbolUnicode(QChar(0x22B6)).addMathOperatorHtml("⊶"); + symbols["mapsto"]=MathOperatorSymbolUnicode(QChar(0x21A6)).addMathOperatorHtml("↦"); + symbols["mid"]=MathOperatorSymbolUnicode(QChar(0x2223)).addMathOperatorHtml("∣").addMathOperatorWinSymbol(QChar(0xBD)).addMathOperatorStd("|"); + symbols["mp"]=MathOperatorSymbolUnicode(QChar(0x2213)).addMathOperatorHtml("∓"); + symbols["multimap"]=MathOperatorSymbolUnicode(QChar(0x22B8)).addMathOperatorHtml("⊸"); + symbols["nabla"]=MathOperatorSymbolUnicode(QChar(0x2207)).addMathOperatorHtml("∇").addMathOperatorWinSymbol(QChar(0xD1)); + symbols["ne"]=MathOperatorSymbolUnicode(QChar(0x2260)).addMathOperatorHtml("≠").addMathOperatorWinSymbol(QChar(0xB9)); + symbols["nearrow"]=UprightSymbolUnicode(QChar(0x2197)).addUprightHtml("↗"); + symbols["neg"]=symbols["lnot"]=MathOperatorSymbolUnicode(QChar(0x00AC)).addMathOperatorHtml("¬").addMathOperatorWinSymbol(QChar(0xD8)); + symbols["neq"]=MathOperatorSymbolUnicode(QChar(0x2260)).addMathOperatorHtml("≠").addMathOperatorWinSymbol(QChar(0xB9)).addStd("=", ItalicOff|BoldOff|DrawSlash); + symbols["nexists"]=MathOperatorSymbolUnicode(QChar(0x2204)).addMathOperatorHtml("∄").addStd("E", ItalicOff|BoldOff|FlipLeftRight|DrawSlash).addMathOperatorWinSymbol(QChar(0x24), ItalicOff|BoldOff|DrawSlash); + symbols["ni"]=MathOperatorSymbolUnicode(QChar(0x220B)).addMathOperatorHtml("∋").addMathOperatorWinSymbol(QChar(0xCE), ItalicOff|BoldOff|FlipLeftRight); + symbols["nmid"]=MathOperatorSymbolUnicode(QChar(0x2224)).addMathOperatorHtml("∤"); + symbols["notin"]=MathOperatorSymbolUnicode(QChar(0x2209)).addMathOperatorHtml("∉").addMathOperatorWinSymbol(QChar(0xCF)); + symbols["notni"]=MathOperatorSymbolUnicode(QChar(0x220C)).addMathOperatorHtml("∌"); + symbols["nparallel"]=MathOperatorSymbolUnicode(QChar(0x2226)).addMathOperatorHtml("∦"); + symbols["nwarrow"]=UprightSymbolUnicode(QChar(0x2196)).addUprightHtml("↖"); + symbols["odot"]=MathOperatorSymbolUnicode(QChar(0x2299)).addMathOperatorHtml("⊙"); + symbols["oiiint"]=MathOperatorSymbolUnicode(QChar(0x2230)).setGlobalFlags(IntLikeSymbolCorrection).addMathOperatorHtml("∰"); + symbols["oiint"]=MathOperatorSymbolUnicode(QChar(0x222F)).setGlobalFlags(IntLikeSymbolCorrection).addMathOperatorHtml("∯"); + symbols["oint"]=MathOperatorSymbolUnicode(QChar(0x222E)).setGlobalFlags(IntLikeSymbolCorrection).addMathOperatorHtml("∮"); + symbols["ominus"]=MathOperatorSymbolUnicode(QChar(0x2296)).addMathOperatorHtml("⊖"); + symbols["oplus"]=MathOperatorSymbolUnicode(QChar(0x2295)).addMathOperatorHtml("⊕").addMathOperatorWinSymbol(QChar(0xC5)); + symbols["oslash"]=MathOperatorSymbolUnicode(QChar(0x2298)).addMathOperatorHtml("⊘"); + symbols["otimes"]=MathOperatorSymbolUnicode(QChar(0x2297)).addMathOperatorHtml("⊗").addMathOperatorWinSymbol(QChar(0xC4)); + symbols["parallel"]=MathOperatorSymbolUnicode(QChar(0x2225)).addMathOperatorHtml("∥").addMathOperatorStd("||"); + symbols["pm"] = MathOperatorSymbol(QChar(0xB1), "±").addMathOperatorWinSymbol(QChar(0xB1)); + symbols["prec"]=MathOperatorSymbolUnicode(QChar(0x227A)).addMathOperatorHtml("≺"); + symbols["prod"]=MathOperatorSymbolUnicode(QChar(0x220F)).addMathOperatorWinSymbol(QChar(0xD5), 1.8, 0.1).addMathOperatorHtml("∏"); + symbols["propto"]=MathOperatorSymbolUnicode(QChar(0x221D)).addMathOperatorWinSymbol(QChar(0xB5)).addMathOperatorHtml("∝"); + symbols["rightharpoondown"]=UprightSymbolUnicode(QChar(0x21C1)).addUprightHtml("⇁"); + symbols["rightharpoonup"]=UprightSymbolUnicode(QChar(0x21C0)).addUprightHtml("⇀"); + symbols["rightleftharpoon"]=UprightSymbolUnicode(QChar(0x21CC)).addUprightHtml("⇌"); + symbols["searrow"]=UprightSymbolUnicode(QChar(0x2198)).addUprightHtml("↘"); + symbols["setminus"]=MathOperatorSymbolUnicode(QChar(0x2216)).addMathOperatorHtml("∖"); + symbols["~"]=symbols["sim"]=symbols["tilde"]=MathOperatorSymbolUnicode(QChar(0x223C)).addMathOperatorHtml("˜").addMathOperatorStd("~"); + symbols["simeq"]=MathOperatorSymbolUnicode(QChar(0x2243)).addMathOperatorHtml("≃"); + symbols["sqcap"]=MathOperatorSymbolUnicode(QChar(0x2293)).addMathOperatorHtml("⊓"); + symbols["sqcup"]=MathOperatorSymbolUnicode(QChar(0x2294)).addMathOperatorHtml("⊔"); + symbols["square"]=MathOperatorSymbolUnicode(QChar(0x25A1)); + symbols["subset"]=MathOperatorSymbolUnicode(QChar(0x2282)).addMathOperatorHtml("⊂").addMathOperatorWinSymbol(QChar(0xCC)); + symbols["subseteq"]=MathOperatorSymbolUnicode(QChar(0x2286)).addMathOperatorHtml("⊆").addMathOperatorWinSymbol(QChar(0xCD)); + symbols["subsetnot"]=MathOperatorSymbolUnicode(QChar(0x2284)).addMathOperatorHtml("⊄").addMathOperatorWinSymbol(QChar(0xCB)); + symbols["succ"]=MathOperatorSymbolUnicode(QChar(0x227B)).addMathOperatorHtml("≻"); + symbols["sum"]=MathOperatorSymbolUnicode(QChar(0x2211)).addMathOperatorWinSymbol(QChar(0xE5), 1.8, 0.1).addMathOperatorHtml("∑"); + symbols["supset"]=MathOperatorSymbolUnicode(QChar(0x2283)).addMathOperatorHtml("⊃").addMathOperatorWinSymbol(QChar(0xC9)); + symbols["supseteq"]=MathOperatorSymbolUnicode(QChar(0x2287)).addMathOperatorHtml("⊇").addMathOperatorWinSymbol(QChar(0xCA)); + symbols["supsetnot"]=MathOperatorSymbolUnicode(QChar(0x2285)).addMathOperatorHtml("⊅"); + symbols["swarrow"]=UprightSymbolUnicode(QChar(0x2199)).addUprightHtml("↙"); + symbols["therefore"]=MathOperatorSymbolUnicode(QChar(0x2234)).addMathOperatorHtml("∴").addMathOperatorWinSymbol(QChar(0x5C)); + symbols["times"] = MathOperatorSymbol(QChar(0xD7), "×").addMathOperatorWinSymbol(QChar(0xB4)); + symbols["to"]=symbols["rightarrow"]=UprightSymbolUnicode(QChar(0x2192)).addUprightHtml("→").addUprightWinSymbol(QChar(0xAE)); + symbols["top"]=MathOperatorSymbolUnicode(QChar(0x22A4)).addMathOperatorHtml("⊤").addMathOperatorWinSymbol(QChar(0x5E)); + symbols["triangle"]=MathOperatorSymbolUnicode(QChar(0x2206)); + symbols["uparrow"]=UprightSymbolUnicode(QChar(0x2191)).addUprightHtml("↑").addUprightWinSymbol(QChar(0xAD)); + symbols["updownarrow"]=UprightSymbolUnicode(QChar(0x2195)).addUprightHtml("↕"); + symbols["upharpoonleft"]=UprightSymbolUnicode(QChar(0x21BF)).addUprightHtml("↿"); + symbols["upharpoonright"]=UprightSymbolUnicode(QChar(0x21BE)).addUprightHtml("↾"); + symbols["vartriangleleft"]=MathOperatorSymbolUnicode(QChar(0x22B2)).addMathOperatorHtml("⊲"); + symbols["vdots"]=MathOperatorSymbolUnicode(QChar(0x22EE)).addMathOperatorHtml("⋮"); + symbols["vee"]=MathOperatorSymbolUnicode(QChar(0x2228)).addMathOperatorHtml("∨").addMathOperatorWinSymbol(QChar(0xDA)); + symbols["wedge"]=MathOperatorSymbolUnicode(QChar(0x2227)).addMathOperatorHtml("∧").addMathOperatorWinSymbol(QChar(0xD9)); + + + + /************************************************************************************** + * GREEK letters + **************************************************************************************/ + symbols["alpha"]=GreekLetter_WinSymbol_Unicode_Html( "a", QChar(0x3B1), "α"); + symbols["beta"]=GreekLetter_WinSymbol_Unicode_Html("b", QChar(0x3B2), "β"); + symbols["gamma"]=GreekLetter_WinSymbol_Unicode_Html("g", QChar(0x3B3), "γ"); + symbols["delta"]=GreekLetter_WinSymbol_Unicode_Html("d", QChar(0x3B4), "δ"); + symbols["epsilon"]=GreekLetter_WinSymbol_Unicode_Html("e", QChar(0x3F5), "ϵ"); + symbols["varepsilon"]=GreekLetter_WinSymbol_Unicode_Html("e", QChar(0x3B5), "ε"); + symbols["zeta"]=GreekLetter_WinSymbol_Unicode_Html("z", QChar(0x3B6),"ζ"); + symbols["eta"]=GreekLetter_WinSymbol_Unicode_Html("h", QChar(0x3B7),"η"); + symbols["theta"]=GreekLetter_WinSymbol_Unicode_Html("q", QChar(0x3B8),"θ"); + symbols["vartheta"]=GreekLetter_WinSymbol_Unicode_Html("J", QChar(0x3D1),"ϑ"); + symbols["iota"]=GreekLetter_WinSymbol_Unicode_Html("i", QChar(0x3B9),"ι"); + symbols["kappa"]=GreekLetter_WinSymbol_Unicode_Html("k", QChar(0x3BA),"κ"); + symbols["lambda"]=GreekLetter_WinSymbol_Unicode_Html("l", QChar(0x3BB),"λ"); + symbols["mu"]=GreekLetter_WinSymbol_Unicode_Html("m", QChar(0x3BC),"μ"); + symbols["nu"]=GreekLetter_WinSymbol_Unicode_Html("n", QChar(0x3BD),"ν"); + symbols["xi"]=GreekLetter_WinSymbol_Unicode_Html("x", QChar(0x3BE),"ξ"); + symbols["pi"]=GreekLetter_WinSymbol_Unicode_Html("p", QChar(0x3C0),"π"); + symbols["varpi"]=GreekLetter_WinSymbol_Unicode_Html("v", QChar(0x3D6),"ϖ"); + symbols["rho"]=GreekLetter_WinSymbol_Unicode_Html("r", QChar(0x3C1),"ρ"); + symbols["varrho"]=GreekLetter_WinSymbol_Unicode_Html("r", QChar(0x3F1),"ϱ"); + symbols["sigma"]=GreekLetter_WinSymbol_Unicode_Html("s", QChar(0x3C3),"σ"); + symbols["varsigma"]=GreekLetter_WinSymbol_Unicode_Html("V", QChar(0x3C2),"ς"); + symbols["tau"]=GreekLetter_WinSymbol_Unicode_Html("t", QChar(0x3C4),"τ"); + symbols["upsilon"]=GreekLetter_WinSymbol_Unicode_Html("u", QChar(0x3C5),"υ"); + symbols["phi"]=GreekLetter_WinSymbol_Unicode_Html("f", QChar(0x3D5),"ϕ"); + symbols["varphi"]=GreekLetter_WinSymbol_Unicode_Html("j", QChar(0x3C6),"φ"); + symbols["chi"]=GreekLetter_WinSymbol_Unicode_Html("c", QChar(0x3C7),"χ"); + symbols["psi"]=GreekLetter_WinSymbol_Unicode_Html("y", QChar(0x3C8),"ψ"); + symbols["omega"]=GreekLetter_WinSymbol_Unicode_Html("w", QChar(0x3C9),"ω"); + symbols["Gamma"]=GreekLetter_WinSymbol_Unicode_Html("G", QChar(0x3A9),"Γ"); + symbols["Delta"]=GreekLetter_WinSymbol_Unicode_Html("D", QChar(0x394),"Δ"); + symbols["Theta"]=GreekLetter_WinSymbol_Unicode_Html("Q", QChar(0x398),"Θ"); + symbols["Lambda"]=GreekLetter_WinSymbol_Unicode_Html("L", QChar(0x39B),"Λ"); + symbols["Omega"]=GreekLetter_WinSymbol_Unicode_Html("W", QChar(0x3A9),"Ω"); + symbols["Xi"]=GreekLetter_WinSymbol_Unicode_Html("X", QChar(0x39E),"Ξ"); + symbols["Pi"]=GreekLetter_WinSymbol_Unicode_Html("P", QChar(0x3A0),"Π"); + symbols["Sigma"]=GreekLetter_WinSymbol_Unicode_Html("S", QChar(0x3A3),"Σ"); + symbols["Upsilon"]=GreekLetter_WinSymbol_Unicode_Html("U", QChar(0x3C6),"Υ"); + symbols["Phi"]=GreekLetter_WinSymbol_Unicode_Html("F", QChar(0x3A6),"Φ"); + symbols["Psi"]=GreekLetter_WinSymbol_Unicode_Html("Y", QChar(0x3A8),"Ψ"); + + + +} + + +JKQTMathTextSymbolNode::SymbolFullProps::SymbolFullProps(): + customFontFamily(), + html(), + fontType(MTECurrentFont), + globalFlags(NoGLobalSymbolFlags) +{ + +} + +JKQTMathTextSymbolNode::SymbolFullProps::SymbolFullProps(const QString &_font, const SymbolProps &props, const QString &_html, SymbolFlags _htmlflags, double _htmlfontScalingFactor, double _htmlyShiftFactor): + customFontFamily(_font), + html(_html, _htmlflags, _htmlfontScalingFactor, _htmlyShiftFactor), + fontType(MTECustomFont), + globalFlags(NoGLobalSymbolFlags) +{ + this->props[MTFEStandard]=props; +} + +JKQTMathTextSymbolNode::SymbolFullProps::SymbolFullProps(const QString &_font, const QString &symbol, const QString &_html, SymbolFlags _htmlflags, double _htmlfontScalingFactor, double _htmlyShiftFactor): + customFontFamily(_font), + html(_html, _htmlflags, _htmlfontScalingFactor, _htmlyShiftFactor), + fontType(MTECustomFont), + globalFlags(NoGLobalSymbolFlags) +{ + this->props[MTFEStandard]=SymbolProps(symbol); +} + +JKQTMathTextSymbolNode::SymbolFullProps::SymbolFullProps(const SymbolProps &props, const QString &_html, SymbolFlags _htmlflags, double _htmlfontScalingFactor, double _htmlyShiftFactor): + customFontFamily(), + html(_html, _htmlflags, _htmlfontScalingFactor, _htmlyShiftFactor), + fontType(MTECurrentFont), + globalFlags(NoGLobalSymbolFlags) +{ + this->props[MTFEStandard]=props; +} + +JKQTMathTextSymbolNode::SymbolFullProps::SymbolFullProps(JKQTMathTextEnvironmentFont _fontType, const SymbolProps &props, const QString &_html, SymbolFlags _htmlflags, double _htmlfontScalingFactor, double _htmlyShiftFactor): + customFontFamily(), + html(_html, _htmlflags, _htmlfontScalingFactor, _htmlyShiftFactor), + fontType(_fontType), + globalFlags(NoGLobalSymbolFlags) +{ + this->props[MTFEStandard]=props; +} + +JKQTMathTextSymbolNode::SymbolFullProps::SymbolFullProps(JKQTMathTextEnvironmentFont _fontType, const QString &symbol, const QString &_html, SymbolFlags _htmlflags, double _htmlfontScalingFactor, double _htmlyShiftFactor): + customFontFamily(), + html(_html, _htmlflags, _htmlfontScalingFactor, _htmlyShiftFactor), + fontType(_fontType), + globalFlags(NoGLobalSymbolFlags) +{ + this->props[MTFEStandard]=SymbolProps(symbol); +} + +JKQTMathTextSymbolNode::SymbolFullProps::SymbolFullProps(JKQTMathTextFontEncoding enc0, const SymbolProps &props0, const QString &_html, SymbolFlags _htmlflags, double _htmlfontScalingFactor, double _htmlyShiftFactor): + customFontFamily(), + html(_html, _htmlflags, _htmlfontScalingFactor, _htmlyShiftFactor), + fontType(MTECurrentFont), + globalFlags(NoGLobalSymbolFlags) +{ + this->props[enc0]=props0; +} + +JKQTMathTextSymbolNode::SymbolFullProps::SymbolFullProps(JKQTMathTextEnvironmentFont _fontType, JKQTMathTextFontEncoding enc0, const SymbolProps &props0, const QString &_html, SymbolFlags _htmlflags, double _htmlfontScalingFactor, double _htmlyShiftFactor): + customFontFamily(), + html(_html, _htmlflags, _htmlfontScalingFactor, _htmlyShiftFactor), + fontType(_fontType), + globalFlags(NoGLobalSymbolFlags) +{ + this->props[enc0]=props0; +} + +JKQTMathTextSymbolNode::SymbolFullProps::SymbolFullProps(JKQTMathTextFontEncoding enc0, const SymbolProps &props0, JKQTMathTextFontEncoding enc1, const SymbolProps &props1, const QString &_html, SymbolFlags _htmlflags, double _htmlfontScalingFactor, double _htmlyShiftFactor): + customFontFamily(), + html(_html, _htmlflags, _htmlfontScalingFactor, _htmlyShiftFactor), + fontType(MTECurrentFont), + globalFlags(NoGLobalSymbolFlags) +{ + this->props[enc0]=props0; + this->props[enc1]=props1; +} + +JKQTMathTextSymbolNode::SymbolFullProps::SymbolFullProps(JKQTMathTextEnvironmentFont _fontType, JKQTMathTextFontEncoding enc0, const SymbolProps &props0, JKQTMathTextFontEncoding enc1, const SymbolProps &props1, const QString &_html, SymbolFlags _htmlflags, double _htmlfontScalingFactor, double _htmlyShiftFactor): + customFontFamily(), + html(_html, _htmlflags, _htmlfontScalingFactor, _htmlyShiftFactor), + fontType(_fontType), + globalFlags(NoGLobalSymbolFlags) +{ + this->props[enc0]=props0; + this->props[enc1]=props1; +} + +JKQTMathTextSymbolNode::SymbolFullProps::SymbolFullProps(JKQTMathTextFontEncoding enc0, const SymbolProps &props0, JKQTMathTextFontEncoding enc1, const SymbolProps &props1, JKQTMathTextFontEncoding enc2, const SymbolProps &props2, const QString &_html, SymbolFlags _htmlflags, double _htmlfontScalingFactor, double _htmlyShiftFactor): + customFontFamily(), + html(_html, _htmlflags, _htmlfontScalingFactor, _htmlyShiftFactor), + fontType(MTECurrentFont), + globalFlags(NoGLobalSymbolFlags) +{ + this->props[enc0]=props0; + this->props[enc1]=props1; + this->props[enc2]=props2; +} + +JKQTMathTextSymbolNode::SymbolFullProps::SymbolFullProps(JKQTMathTextEnvironmentFont _fontType, JKQTMathTextFontEncoding enc0, const SymbolProps &props0, JKQTMathTextFontEncoding enc1, const SymbolProps &props1, JKQTMathTextFontEncoding enc2, const SymbolProps &props2, const QString &_html, SymbolFlags _htmlflags, double _htmlfontScalingFactor, double _htmlyShiftFactor): + customFontFamily(), + html(_html, _htmlflags, _htmlfontScalingFactor, _htmlyShiftFactor), + fontType(_fontType), + globalFlags(NoGLobalSymbolFlags) +{ + this->props[enc0]=props0; + this->props[enc1]=props1; + this->props[enc2]=props2; +} + +JKQTMathTextSymbolNode::SymbolFullProps &JKQTMathTextSymbolNode::SymbolFullProps::add(JKQTMathTextFontEncoding enc, const SymbolProps &_props) +{ + props[enc]=_props; + return *this; +} + +JKQTMathTextSymbolNode::SymbolFullProps &JKQTMathTextSymbolNode::SymbolFullProps::addWinSymbol(const QString &_symbol, SymbolFlags _flags, double _fontScalingFactor, double _yShiftFactor) +{ + props[MTFEWinSymbol]=SymbolProps(_symbol, _flags, _fontScalingFactor, _yShiftFactor); + return *this; +} + +JKQTMathTextSymbolNode::SymbolFullProps &JKQTMathTextSymbolNode::SymbolFullProps::addMathOperatorWinSymbol(const QString &_symbol, double _fontScalingFactor, double _yShiftFactor) +{ + props[MTFEWinSymbol]=SymbolProps(_symbol, ItalicOff|BoldOff, _fontScalingFactor, _yShiftFactor); + return *this; +} + +JKQTMathTextSymbolNode::SymbolFullProps &JKQTMathTextSymbolNode::SymbolFullProps::addUprightWinSymbol(const QString &_symbol, double _fontScalingFactor, double _yShiftFactor) +{ + props[MTFEWinSymbol]=SymbolProps(_symbol, ItalicOff, _fontScalingFactor, _yShiftFactor); + return *this; +} + + +JKQTMathTextSymbolNode::SymbolFullProps &JKQTMathTextSymbolNode::SymbolFullProps::addUnicode(const QString &_symbol, SymbolFlags _flags, double _fontScalingFactor, double _yShiftFactor) +{ + props[MTFEUnicode]=SymbolProps(_symbol, _flags, _fontScalingFactor, _yShiftFactor); + return *this; +} + +JKQTMathTextSymbolNode::SymbolFullProps &JKQTMathTextSymbolNode::SymbolFullProps::addUprightUnicode(const QString &_symbol, double _fontScalingFactor, double _yShiftFactor) +{ + props[MTFEUnicode]=SymbolProps(_symbol, ItalicOff, _fontScalingFactor, _yShiftFactor); + return *this; +} + +JKQTMathTextSymbolNode::SymbolFullProps &JKQTMathTextSymbolNode::SymbolFullProps::addMathOperatorUnicode(const QString &_symbol, double _fontScalingFactor, double _yShiftFactor) +{ + props[MTFEUnicode]=SymbolProps(_symbol, ItalicOff|BoldOff, _fontScalingFactor, _yShiftFactor); + return *this; +} + +JKQTMathTextSymbolNode::SymbolFullProps &JKQTMathTextSymbolNode::SymbolFullProps::addStd(const QString &_symbol, SymbolFlags _flags, double _fontScalingFactor, double _yShiftFactor) +{ + props[MTFEStandard]=SymbolProps(_symbol, _flags, _fontScalingFactor, _yShiftFactor); + return *this; +} + +JKQTMathTextSymbolNode::SymbolFullProps &JKQTMathTextSymbolNode::SymbolFullProps::addMathOperatorStd(const QString &_symbol, double _fontScalingFactor, double _yShiftFactor) +{ + props[MTFEStandard]=SymbolProps(_symbol, ItalicOff|BoldOff, _fontScalingFactor, _yShiftFactor); + return *this; +} + +JKQTMathTextSymbolNode::SymbolFullProps &JKQTMathTextSymbolNode::SymbolFullProps::addUprightStd(const QString &_symbol, double _fontScalingFactor, double _yShiftFactor) +{ + props[MTFEStandard]=SymbolProps(_symbol, ItalicOff, _fontScalingFactor, _yShiftFactor); + return *this; +} + +JKQTMathTextSymbolNode::SymbolFullProps &JKQTMathTextSymbolNode::SymbolFullProps::addHtml(const QString &_symbol, SymbolFlags _flags, double _fontScalingFactor, double _yShiftFactor) +{ + html=SymbolProps(_symbol, _flags, _fontScalingFactor, _yShiftFactor); + return *this; +} + +JKQTMathTextSymbolNode::SymbolFullProps &JKQTMathTextSymbolNode::SymbolFullProps::addMathOperatorHtml(const QString &_symbol, double _fontScalingFactor, double _yShiftFactor) +{ + html=SymbolProps(_symbol, ItalicOff|BoldOff, _fontScalingFactor, _yShiftFactor); + return *this; +} + +JKQTMathTextSymbolNode::SymbolFullProps &JKQTMathTextSymbolNode::SymbolFullProps::addUprightHtml(const QString &_symbol, double _fontScalingFactor, double _yShiftFactor) +{ + html=SymbolProps(_symbol, ItalicOff, _fontScalingFactor, _yShiftFactor); + return *this; +} + +JKQTMathTextSymbolNode::SymbolFullProps &JKQTMathTextSymbolNode::SymbolFullProps::addGlobalFlags(GlobalSymbolFlags addglobalFlags) +{ + globalFlags |= addglobalFlags; + return *this; +} + +JKQTMathTextSymbolNode::SymbolFullProps &JKQTMathTextSymbolNode::SymbolFullProps::setGlobalFlags(GlobalSymbolFlags addglobalFlags) +{ + globalFlags = addglobalFlags; + return *this; +} + +QPair JKQTMathTextSymbolNode::SymbolFullProps::getDrawingData(JKQTMathTextEnvironment currentEv, JKQTMathText* parent) const +{ + SymbolProps outProps; + QFont outFont; + const JKQTMathTextFontEncoding currentEnc=currentEv.getFontEncoding(parent); + QFont currentFont=currentEv.getFont(parent); + currentFont.setStyleStrategy(QFont::NoFontMerging); + const QFontMetricsF currentFM(currentFont); + QFont fallbackGreekFont=parent->getFallbackFontGreek(); + fallbackGreekFont.setStyleStrategy(QFont::NoFontMerging); + const QFontMetricsF fallbackGreekFM(fallbackGreekFont); + QFont fallbackSymbolsFont=parent->getFallbackFontSymbols(); + fallbackSymbolsFont.setStyleStrategy(QFont::NoFontMerging); + const QFontMetricsF fallbackSymbolsFM(fallbackSymbolsFont); + + if (fontType==MTEFallbackGreek) { + if (currentEnc!=MTFEStandard && props.contains(currentEnc)) { + outProps=props[currentEnc]; + const QChar ch=props[currentEnc].getSymbolSingleChar(); + if (!ch.isNull() && !currentFM.inFont(ch)) { + currentEv.font=MTEFallbackGreek; + outProps=props.value(currentEv.getFontEncoding(parent), outProps); + } + } else if (currentEnc==MTFEStandard && props.contains(currentEnc)){ + outProps=props[currentEnc]; + const QChar ch=props[currentEnc].getSymbolSingleChar(); + if (!ch.isNull() && fallbackGreekFM.inFont(ch)) { + currentEv.font=MTEFallbackGreek; + outProps=props.value(currentEv.getFontEncoding(parent), outProps); + } + } else { + currentEv.font=MTEFallbackGreek; + } + } else if (fontType==MTEFallbackSymbols) { + if (currentEnc!=MTFEStandard && props.contains(currentEnc)) { + outProps=props[currentEnc]; + const QChar ch=props[currentEnc].getSymbolSingleChar(); + if (!ch.isNull() && !currentFM.inFont(ch)) { + currentEv.font=MTEFallbackGreek; + outProps=props.value(currentEv.getFontEncoding(parent), outProps); + } + } else if (currentEnc==MTFEStandard && props.contains(currentEnc)){ + outProps=props[currentEnc]; + const QChar ch=props[currentEnc].getSymbolSingleChar(); + if (!ch.isNull() && fallbackSymbolsFM.inFont(ch)) { + currentEv.font=MTEFallbackSymbols; + outProps=props.value(currentEv.getFontEncoding(parent), outProps); + } + } else { + currentEv.font=MTEFallbackGreek; + } + } else if (fontType!=MTEEnvironmentFontCount) { + if (fontType!=MTECurrentFont) { + currentEv.font=fontType; + } + if (fontType==MTECustomFont) { + currentEv.customFontName=customFontFamily; + outProps=props.value(MTFEStandard, outProps); + } else { + QFont lcurrentFont=currentEv.getFont(parent); + lcurrentFont.setStyleStrategy(QFont::NoFontMerging); + const QFontMetricsF lcurrentFM(lcurrentFont); + auto lcurrentEnc=currentEv.getFontEncoding(parent); + outProps=props.value(lcurrentEnc, props.value(MTFEStandard, outProps)); + const QChar ch=outProps.getSymbolSingleChar(); + if (!ch.isNull() && !lcurrentFM.inFont(ch) && fallbackSymbolsFM.inFont(ch)) { + currentEv.font=MTEFallbackSymbols; + outProps=props.value(currentEv.getFontEncoding(parent), outProps); + } + } + if (props.contains(currentEv.getFontEncoding(parent))) outProps=props[currentEv.getFontEncoding(parent)]; + } + outFont=currentEv.getFont(parent); + if (outProps.fontScalingFactor!=1) outFont.setPointSizeF(outFont.pointSizeF()*outProps.fontScalingFactor); + if (has(outProps.flags, ItalicOn)) outFont.setItalic(true); + if (has(outProps.flags, ItalicOff)) outFont.setItalic(false); + if (has(outProps.flags, BoldOn)) outFont.setBold(true); + if (has(outProps.flags, BoldOff)) outFont.setBold(false); + return QPair(outFont, outProps); +} diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.h b/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.h index c564a7dcfa..ca8321f9b4 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.h +++ b/lib/jkqtmathtext/nodes/jkqtmathtextsymbolnode.h @@ -27,6 +27,7 @@ #include "jkqtmathtext/jkqtmathtexttools.h" #include "jkqtmathtext/nodes/jkqtmathtextnode.h" #include +#include class JKQTMathText; // forward // JKQTMATHTEXT_LIB_EXPORT @@ -34,6 +35,25 @@ class JKQTMathText; // forward /** \brief subclass representing one symbol (e.g. \c \\alpha , \c \\cdot ...) node in the syntax tree * \ingroup jkqtmathtext_items + * + * All supported symbols are stored in the static table symbols, which is filled by fillSymbolTable(). + * The latter function is also the customization point for new symbols: + * - For each symbol, the instruction name is stored as key, e.g. for \c \\alpha the key \c "alpha" is stored. + * - for each instruction a SymbolFullProps describes the symbol and stores how to draw it. + * - Each symbol has global properties (GlobalSymbolFlags, e.g. how to treat it's with etz.) and a set of representations. + * Each representation is for one font-encoding (JKQTMathTextFontEncoding, i.e. Unicode, WinSymbol or Standard) + * - each encoding representation SymbolProps specifies a text to represent the symol in SymbolProps::symbol and + * can have additional flags, properties etc. + * . + * + * Font Lookup for symbols works as follows in JKQTMathTextSymbolNode: + * - if a character is found in the current (or to be used) font, it is taken from there (the font is specified in + * SymbolFullProps::fontType) + * - if the character is not found, it is looked for in the fallback fonts MTEFallbackGreek and MTEFallbackSymbols + * - as a last resort, some symbols can be created otherwise, so if neither of the two options above + * contain the required symbol, the symbol might be synthesized otherwise, or a rectangle with the size of "X" is drawn instead + * . + * */ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSymbolNode: public JKQTMathTextNode { public: @@ -47,8 +67,6 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSymbolNode: public JKQTMathTextNode { 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; /** \brief determine the size of the node, calls getSizeInternal() implementation of the actual type \see getSizeInternal() @@ -65,49 +83,186 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSymbolNode: public JKQTMathTextNode { * */ void getSymbolSize(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, double& subSuperXCorrection, double& subBesidesXCorrection, const JKQTMathTextNodeSize* prevNodeSize=nullptr); + /** \brief checks whether the given symbol name can be prepresented by this type of node */ + static bool hasSymbol(const QString& symbolName); 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::getSizeInternal() */ virtual void getSymbolSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, double& subSuperXCorrection, double& subBesidesXCorrection, const JKQTMathTextNodeSize* prevNodeSize=nullptr) ; + /** \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 flags specifying additional symbol features */ + enum SymbolFlags: uint64_t { + AsOutside= 0, /*!< \brief indicates that no properties are activated */ + ItalicOn= 1 << 0, /*!< \brief make font italic in any case */ + ItalicOff= 1 << 1, /*!< \brief make font non-italic (i.e. upright) in any case */ + BoldOn= 1 << 2, /*!< \brief make font bold in any case */ + BoldOff= 1 << 3, /*!< \brief make font non-bold (i,,e, normal weight) in any case */ + DrawBar= 1 << 4, /*!< \brief indicates whether to draw a bar (like for \c \\hbar ) */ + FlipUpDown=1 << 5, /*!< \brief indicates to flip the given symbol upside-down */ + FlipLeftRight=1 << 6, /*!< \brief indicates to flip the given symbol left-right */ + Rotate90=1 << 7, /*!< \brief indicates to rotate the symbol 90 degree */ + DrawSlash=1 << 8, /*!< \brief indicates to overdraw a backslash (e.g. to combine 0 and / to form \\varnothing ) */ + HeightIsAscent= 1 << 9, /*!< \brief if true, the height of the symbol equals the ascent of the font */ + Upright=ItalicOff, + NormalWeight=BoldOff, }; + + friend inline SymbolFlags operator~ (SymbolFlags a) { return (SymbolFlags)~static_cast(a); } + friend inline SymbolFlags operator| (SymbolFlags a, SymbolFlags b) { return static_cast(static_cast(a) | static_cast(b)); } + friend inline SymbolFlags operator& (SymbolFlags a, SymbolFlags b) { return static_cast(static_cast(a) & static_cast(b)); } + friend inline SymbolFlags operator^ (SymbolFlags a, SymbolFlags b) { return static_cast(static_cast(a) ^ static_cast(b)); } + friend inline SymbolFlags& operator|= (SymbolFlags& a, SymbolFlags b) { return reinterpret_cast(reinterpret_cast(a) |= static_cast(b)); } + friend inline SymbolFlags& operator&= (SymbolFlags& a, SymbolFlags b) { return reinterpret_cast(reinterpret_cast(a) &= static_cast(b)); } + friend inline SymbolFlags& operator^= (SymbolFlags& a, SymbolFlags b) { return reinterpret_cast(reinterpret_cast(a) ^= static_cast(b)); } + friend inline bool has(SymbolFlags a, SymbolFlags b) { return (a&b)==b; } + + /** \brief flags specifying additional symbol features */ + enum GlobalSymbolFlags: uint64_t { + NoGLobalSymbolFlags= 0, /*!< \brief indicates that no properties are activated */ + ExtendWidthInMathmode= 1 << 0, /*!< \brief this symbol has an extended width, when used within a moth-environment/in math-mode */ + MakeWhitespaceHalf= 1 << 1, /*!< \brief symbol uses whitespaces in its text (SymbolProps::symbol). These should be typeset as half-spaces */ + IntLikeSymbolCorrection= 1 << 2, /*!< \brief symbols, like \c \\int,\\iint,... require a correction in x-direction for subsequent sub-/superscripts ... this flag marks such symbols */ + }; + + friend inline GlobalSymbolFlags operator~ (GlobalSymbolFlags a) { return (GlobalSymbolFlags)~static_cast(a); } + friend inline GlobalSymbolFlags operator| (GlobalSymbolFlags a, GlobalSymbolFlags b) { return static_cast(static_cast(a) | static_cast(b)); } + friend inline GlobalSymbolFlags operator& (GlobalSymbolFlags a, GlobalSymbolFlags b) { return static_cast(static_cast(a) & static_cast(b)); } + friend inline GlobalSymbolFlags operator^ (GlobalSymbolFlags a, GlobalSymbolFlags b) { return static_cast(static_cast(a) ^ static_cast(b)); } + friend inline GlobalSymbolFlags& operator|= (GlobalSymbolFlags& a, GlobalSymbolFlags b) { return reinterpret_cast(reinterpret_cast(a) |= static_cast(b)); } + friend inline GlobalSymbolFlags& operator&= (GlobalSymbolFlags& a, GlobalSymbolFlags b) { return reinterpret_cast(reinterpret_cast(a) &= static_cast(b)); } + friend inline GlobalSymbolFlags& operator^= (GlobalSymbolFlags& a, GlobalSymbolFlags b) { return reinterpret_cast(reinterpret_cast(a) ^= static_cast(b)); } + friend inline bool has(GlobalSymbolFlags a, GlobalSymbolFlags b) { return (a&b)==b; } + + /** \brief calculates the bounding rect of \a text using \a fm and taking the flags from \a globalFlags into account */ + static QRectF getBoundingRect(const QFontMetricsF& fm, const QString& text, GlobalSymbolFlags globalFlags); + /** \brief calculates the tight bounding rect of \a text using \a fm and taking the flags from \a globalFlags into account */ + static QRectF getTightBoundingRect(const QFontMetricsF& fm, const QString& text, GlobalSymbolFlags globalFlags); + /** \brief draw \a text at (0,0) using QPainter \a p and taking the flags from \a globalFlags into account */ + static void drawText(QPainter &p, const QString &text, GlobalSymbolFlags globalFlags); + + /** \brief properties of the symbol */ + struct SymbolProps { + SymbolProps(); + /** \brief this constructor sets the given properties and sets html=symbol! replaces whitespaces in \a _ymbol with \c   for html, iff MakeWhitespaceHalf is set in \a _flags*/ + SymbolProps(const QString& _symbol, SymbolFlags _flags=AsOutside, double _fontScalingFactor=1.0, double _yShiftFactor=0.0); + /** \brief the symbol or text used to render the symbol (i.e. not the name, + * e.g. if the instruction/symbol name \c \\int is used, this would be \c QChar(0xF2) , + * for \c \\sin it would be \c QString("sin") ...) */ + QString symbol; + /** \brief if \a symbol is a single character, this returns it, otherwise (empty or multi-character) it returns QChar() */ + inline QChar getSymbolSingleChar() const { + if (symbol.size()==1) return symbol[0]; + return QChar(); + } + /** \brief flags switching special features */ + SymbolFlags flags; + /** \brief magnification factor for the font size */ + double fontScalingFactor; + /** \brief this corrects the y position of a symbol: draws at y <- y+ height*yfactor) */ + double yShiftFactor; + }; + + /** \brief properties of the symbol, extends SymbolProps with font... */ + struct SymbolFullProps { + /** \brief default constructor */ + SymbolFullProps(); + /** \brief typesets the symbol (described in \a props ) from the specified \a font, \a props is stored with encoding MTFEStandard, an optional HTML-string \A _html can be given */ + SymbolFullProps(const QString& font, const SymbolProps& props, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0); + /** \brief typesets the \a symbol from the specified \a font, \a props is stored with encoding MTFEStandard, an optional HTML-string \A _html can be given */ + SymbolFullProps(const QString& font, const QString& symbol, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0); + /** \brief \a props is stored with encoding MTFEStandard, an optional HTML-string \A _html can be given */ + SymbolFullProps(const SymbolProps& props, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0); + /** \brief \a props is stored with encoding MTFEStandard, uses the specified \a _fontType for drawing, an optional HTML-string \A _html can be given */ + SymbolFullProps(JKQTMathTextEnvironmentFont _fontType, const SymbolProps& props, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0); + /** \brief takes a \a symbol from the specified \a _fontType assuming MTFEStandard encoding, an optional HTML-string \A _html can be given */ + SymbolFullProps(JKQTMathTextEnvironmentFont _fontType, const QString& symbol, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0); + /** \brief single-alternative symbol for encoding \a enc0 and using symbol description \a props0 for it. An optional HTML-string \a _html can be provided */ + SymbolFullProps(JKQTMathTextFontEncoding enc0, const SymbolProps& props0, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0); + /** \brief single-alternative symbol for encoding \a enc0 and using symbol description \a props0 for it, uses the specified \a _fontType for drawing. An optional HTML-string \a _html can be provided */ + SymbolFullProps(JKQTMathTextEnvironmentFont _fontType, JKQTMathTextFontEncoding enc0, const SymbolProps& props0, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0); + /** \brief double-alternative symbol for encoding \a enc0 + \a enc1 and using symbol descriptions \a props0 + \a props1 for it. An optional HTML-string \a _html can be provided */ + SymbolFullProps(JKQTMathTextFontEncoding enc0, const SymbolProps& props0, JKQTMathTextFontEncoding enc1, const SymbolProps& props1, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0); + /** \brief double-alternative symbol for encoding \a enc0 + \a enc1 and using symbol descriptions \a props0 + \a props1 for it, uses the specified \a _fontType for drawing. An optional HTML-string \a _html can be provided */ + SymbolFullProps(JKQTMathTextEnvironmentFont _fontType, JKQTMathTextFontEncoding enc0, const SymbolProps& props0, JKQTMathTextFontEncoding enc1, const SymbolProps& props1, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0); + /** \brief triple-alternative symbol for encoding \a enc0 + \a enc1 + \a enc2 and using symbol descriptions \a props0 + \a props1 + \a props2 for it. An optional HTML-string \a _html can be provided */ + SymbolFullProps(JKQTMathTextFontEncoding enc0, const SymbolProps& props0, JKQTMathTextFontEncoding enc1, const SymbolProps& props1, JKQTMathTextFontEncoding enc2, const SymbolProps& props2, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0); + /** \brief triple-alternative symbol for encoding \a enc0 + \a enc1 + \a enc2 and using symbol descriptions \a props0 + \a props1 + \a props2 for it, uses the specified \a _fontType for drawing. An optional HTML-string \a _html can be provided */ + SymbolFullProps(JKQTMathTextEnvironmentFont _fontType, JKQTMathTextFontEncoding enc0, const SymbolProps& props0, JKQTMathTextFontEncoding enc1, const SymbolProps& props1, JKQTMathTextFontEncoding enc2, const SymbolProps& props2, const QString& _html=QString(), SymbolFlags _htmlflags=AsOutside, double _htmlfontScalingFactor=1.0, double _htmlyShiftFactor=0.0); + /** \brief font type to use for typesetting the symbol (default is MTcurrentFont, which just takes the font set in the surrounding environment) */ + JKQTMathTextEnvironmentFont fontType; + /** \brief font to use for output when fontType==MTcustomFont */ + QString customFontFamily; + /** \brief here the actual symbol properties for each JKQTMathTextFontEncoding are stored */ + QHash props; + /** \brief HTML entity/text to represent the symbol (empty html.symbol not available) */ + SymbolProps html; + /** \brief specifies global symbol flags */ + GlobalSymbolFlags globalFlags; + + SymbolFullProps &add(JKQTMathTextFontEncoding enc, const SymbolProps& props); + SymbolFullProps& addWinSymbol(const QString& _symbol, SymbolFlags _flags=AsOutside, double _fontScalingFactor=1.0, double _yShiftFactor=0.0); + SymbolFullProps& addMathOperatorWinSymbol(const QString& _symbol, double _fontScalingFactor=1.0, double _yShiftFactor=0.0); + SymbolFullProps& addUprightWinSymbol(const QString& _symbol, double _fontScalingFactor=1.0, double _yShiftFactor=0.0); + SymbolFullProps& addUnicode(const QString& _symbol, SymbolFlags _flags=AsOutside, double _fontScalingFactor=1.0, double _yShiftFactor=0.0); + SymbolFullProps& addUprightUnicode(const QString& _symbol, double _fontScalingFactor=1.0, double _yShiftFactor=0.0); + SymbolFullProps& addMathOperatorUnicode(const QString& _symbol, double _fontScalingFactor=1.0, double _yShiftFactor=0.0); + SymbolFullProps& addStd(const QString& _symbol, SymbolFlags _flags=AsOutside, double _fontScalingFactor=1.0, double _yShiftFactor=0.0); + SymbolFullProps& addMathOperatorStd(const QString& _symbol, double _fontScalingFactor=1.0, double _yShiftFactor=0.0); + SymbolFullProps& addUprightStd(const QString& _symbol, double _fontScalingFactor=1.0, double _yShiftFactor=0.0); + SymbolFullProps& addHtml(const QString& _symbol, SymbolFlags _flags=AsOutside, double _fontScalingFactor=1.0, double _yShiftFactor=0.0); + SymbolFullProps& addMathOperatorHtml(const QString& _symbol, double _fontScalingFactor=1.0, double _yShiftFactor=0.0); + SymbolFullProps& addUprightHtml(const QString& _symbol, double _fontScalingFactor=1.0, double _yShiftFactor=0.0); + SymbolFullProps& addGlobalFlags(GlobalSymbolFlags addglobalFlags); + SymbolFullProps& setGlobalFlags(GlobalSymbolFlags addglobalFlags); + + /** \brief returns the QFont to use for drawing and the QString to draw with it */ + QPair getDrawingData(JKQTMathTextEnvironment currentEv, JKQTMathText *parent) const; + }; + + /** \brief creates a SymbolFullProps object for a symbol that can be typeset in any font, for SymbolFullProps::html the same text as a\a symbol is used */ + static SymbolFullProps SimpleTextSymbol(const QString& symbol); + /** \brief creates a SymbolFullProps object for a symbol that can be typeset in any font, a special html-string is given */ + static SymbolFullProps SimpleTextSymbol(const QString& symbol, const QString& html); + /** \brief creates a SymbolFullProps object for a symbol that can be typeset in any font, for SymbolFullProps::html the same text as a\a symbol is used */ + static SymbolFullProps SimpleUprightTextSymbol(const QString& symbol); + /** \brief creates a SymbolFullProps object for a symbol that can be typeset in any font, a special html-string is given */ + static SymbolFullProps SimpleUprightTextSymbol(const QString& symbol, const QString& html); + /** \brief constructs a SymbolProps for a math-operator like \c \\sin ..., i.e. ItalicOff, BoldOff, ExtendWidthInMathmode */ + static SymbolFullProps MathOperatorSymbol(const QString& op); + /** \brief constructs a SymbolProps with explicit HTML for a math-operator like \c \\sin ..., i.e. ItalicOff, BoldOff, ExtendWidthInMathmode */ + static SymbolFullProps MathOperatorSymbol(const QString& op, const QString& ophtml); + /** \brief constructs a SymbolProps for a math-operator like \c \\sin ..., i.e. ItalicOff, BoldOff, HeightIsAscent, ExtendWidthInMathmode */ + static SymbolFullProps MathOperatorText(const QString& op); + /** \brief constructs a SymbolProps with explicit HTML for a math-operator like \c \\sin ..., i.e. ItalicOff, BoldOff, HeightIsAscent, ExtendWidthInMathmode */ + static SymbolFullProps MathOperatorText(const QString& op, const QString& ophtml); + /** \brief constructs a SymbolProps for greek letter with the symbol in unicode-encoding \a letterUnicode and in WinSymbol-encoding letterWinWsymbol */ + static SymbolFullProps GreekLetter_WinSymbol_Unicode_Html(const QString& letterWinSymbol, const QString& letterUnicode, const QString& html); + /** \brief constructs a SymbolProps for a symbol with encoding in Standard-fonts a */ + static SymbolFullProps SymbolStd(const QString& symbol, const QString& html=QString()); + /** \brief constructs a SymbolProps for a symbol with encoding in UnicodeFull-fonts a */ + static SymbolFullProps SymbolUnicode(const QString& symbol, const QString& html=QString()); + /** \brief constructs a SymbolProps for a symbol with encoding in Standard-fonts a */ + static SymbolFullProps UprightSymbolStd(const QString& symbol, const QString& html=QString()); + /** \brief constructs a SymbolProps for a symbol with encoding in UnicodeFull-fonts a */ + static SymbolFullProps UprightSymbolUnicode(const QString& symbol, const QString& html=QString()); + /** \brief constructs a SymbolProps for a math-operator symbol like \c \\pm ... in unicode-full-encoding, i.e. ItalicOff, BoldOff, ExtendWidthInMathmode */ + static SymbolFullProps MathOperatorSymbolUnicode(const QString& unicode); + + /** \brief symbols that can be generated in any standard-font */ + static QHash symbols; + + /** \brief fill the symbol tables standardTextSymbols, winSymbolSymbol, ... with contents */ + static void fillSymbolTables(); + /** \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 ¤tEv, 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 ¤tEv, 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 ¤tEv, 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; + SymbolFullProps getSymbolProp(const QString& symName, const JKQTMathTextEnvironment& currentEv) const; }; #endif // JKQTMATHTEXTSYMBOLNODE_H diff --git a/lib/jkqtmathtext/nodes/jkqtmathtexttextnode.cpp b/lib/jkqtmathtext/nodes/jkqtmathtexttextnode.cpp index 1452c7984a..fed3de5691 100644 --- a/lib/jkqtmathtext/nodes/jkqtmathtexttextnode.cpp +++ b/lib/jkqtmathtext/nodes/jkqtmathtexttextnode.cpp @@ -63,7 +63,6 @@ void JKQTMathTextTextNode::getSizeInternal(QPainter& painter, JKQTMathTextEnviro 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()); @@ -200,7 +199,7 @@ QString JKQTMathTextTextNode::textTransform(const QString &text, JKQTMathTextEnv { QString txt=text; auto fnt=parentMathText->getFontData(currentEv.font, currentEv.insideMath); - if (fnt.second==MTFEunicode || fnt.second==MTFEunicodeLimited) { + if (fnt.second==MTFEUnicode || fnt.second==MTFEUnicode) { if (currentEv.insideMath) { txt=""; for (int i=0; i) + + + + 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 . +*/ + + + +#include "jkqtmathtext/nodes/jkqtmathtextwhitespacenode.h" +#include "jkqtmathtext/jkqtmathtexttools.h" +#include "jkqtmathtext/nodes/jkqtmathtextnode.h" +#include "jkqtmathtext/jkqtmathtext.h" +#include "jkqtcommon/jkqtpcodestructuring.h" +#include "jkqtcommon/jkqtpstringtools.h" +#include +#include +#include +#include +#include +#include +#include + + + + +JKQTMathTextWhitespaceNode::JKQTMathTextWhitespaceNode(Types type, JKQTMathText *_parent): + JKQTMathTextWhitespaceNode(type, 1, _parent) +{ + +} + +JKQTMathTextWhitespaceNode::JKQTMathTextWhitespaceNode(JKQTMathText *_parent): + JKQTMathTextWhitespaceNode(WSTNormal, 1, _parent) +{ + +} + +JKQTMathTextWhitespaceNode::JKQTMathTextWhitespaceNode(const QString &_type, JKQTMathText *parent): + JKQTMathTextWhitespaceNode(parent) +{ + fillSupportedInstructions(); + whitespace=supportedInstructions[_type]; +} + +JKQTMathTextWhitespaceNode::JKQTMathTextWhitespaceNode(const QString &_type, size_t count, JKQTMathText *parent): + JKQTMathTextWhitespaceNode(parent) +{ + fillSupportedInstructions(); + whitespace=supportedInstructions[_type]; + whitespace.count=whitespace.count*count; +} + +JKQTMathTextWhitespaceNode::JKQTMathTextWhitespaceNode(Types type, size_t count, JKQTMathText *parent): + JKQTMathTextNode(parent), + whitespace(type, count) +{ + fillSupportedInstructions(); +} + +JKQTMathTextWhitespaceNode::~JKQTMathTextWhitespaceNode() { + +} + +QString JKQTMathTextWhitespaceNode::getTypeName() const +{ + return QLatin1String("JKQTMathTextWhitespaceNode(")+Type2String(whitespace.type)+", count="+QString::number(whitespace.count)+")"; +} + +bool JKQTMathTextWhitespaceNode::toHtml(QString &html, JKQTMathTextEnvironment /*currentEv*/, JKQTMathTextEnvironment /*defaultEv*/) { + for (size_t i=0; ilogicalDpiX(); + const QFontMetricsF fm(currentEv.getFont(parentMathText)); + width=singelWidthPIX*static_cast(whitespace.count); + baselineHeight=0; + overallHeight=0; + strikeoutPos=fm.strikeOutPos(); +} + +QHash JKQTMathTextWhitespaceNode::supportedInstructions; + +void JKQTMathTextWhitespaceNode::fillSupportedInstructions() +{ + if (supportedInstructions.size()==0) { + supportedInstructions[" "]=WhitespaceProps(WSTthicker, 1); + supportedInstructions["nbsp"]=WhitespaceProps(WSTNonbreaking, 1); + supportedInstructions["enspace"]=WhitespaceProps(WST1en, 1); + supportedInstructions["quad"]=supportedInstructions["emspace"]=WhitespaceProps(WSTQuad, 1); + supportedInstructions["qquad"]=WhitespaceProps(WSTQuad, 2); + supportedInstructions[","]=supportedInstructions["thinspace"]=WhitespaceProps(WSTthin, 1); + supportedInstructions[":"]=supportedInstructions["medspace"]=WhitespaceProps(WSTmedium, 1); + supportedInstructions[";"]=supportedInstructions["thickspace"]=WhitespaceProps(WSTthick, 1); + supportedInstructions["!"]=supportedInstructions["negthinspace"]=WhitespaceProps(WSTnegthin, 1); + supportedInstructions["negmedspace"]=WhitespaceProps(WSTnegmedium, 1); + supportedInstructions["negthickspace"]=WhitespaceProps(WSTnegthick, 1); + } + +} + +QString JKQTMathTextWhitespaceNode::Type2String(Types type) +{ + switch (type) { + case WSTNormal: return "WSTNormal"; + case WSTNonbreaking: return "WSTNonbreaking"; + case WST1en: return "WST1en"; + case WST1em: return "WST1em"; + case WSThair: return "WSThair"; + case WSTthin: return "WSTthin"; + case WSTnegthin: return "WSTnegthin"; + case WSTmedium: return "WSTmedium"; + case WSTnegmedium: return "WSTnegmedium"; + case WSTthick: return "WSTthick"; + case WSTnegthick: return "WSTnegthick"; + case WSTthicker: return "WSTthicker"; + } + return "???"; +} + +double JKQTMathTextWhitespaceNode::Type2PointWidth(Types type, JKQTMathTextEnvironment currentEv) const +{ + const double em=currentEv.fontSize; + const double en=em/2.0; + switch (type) { + case WSTNormal: return QFontMetricsF(currentEv.getFont(parentMathText)).width(' '); + case WSTNonbreaking: return QFontMetricsF(currentEv.getFont(parentMathText)).width(' '); + case WST1en: return en; + case WST1em: return em; + case WSThair: return em/12.0; + case WSTthin: return em/6.0; + case WSTnegthin: return -em/6.0; + case WSTmedium: return em*2.0/9.0; + case WSTnegmedium: return -em*2.0/9.0; + case WSTthick: return em*5.0/18.0; + case WSTnegthick: return -em*5.0/18.0; + case WSTthicker: return em/3.0; + } + return 0.0; +} + + +bool JKQTMathTextWhitespaceNode::supportsInstructionName(const QString &instruction) +{ + fillSupportedInstructions(); + return supportedInstructions.contains(instruction); +} + + +QString JKQTMathTextWhitespaceNode::Type2HTML(Types type) +{ + switch (type) { + case WSTNonbreaking: return " "; + case WST1en: return " "; + case WST1em: return " "; + case WSThair: return "&hairsp"; + case WSTthin: return " "; + case WSTnegthin: return ""; + case WSTmedium: return " "; + case WSTnegmedium: return ""; + case WSTthick: return " "; + case WSTnegthick: return ""; + case WSTthicker: return "  "; + case WSTNormal: + default: + return " "; + } + return " "; +} + diff --git a/lib/jkqtmathtext/nodes/jkqtmathtextwhitespacenode.h b/lib/jkqtmathtext/nodes/jkqtmathtextwhitespacenode.h new file mode 100644 index 0000000000..6b55264770 --- /dev/null +++ b/lib/jkqtmathtext/nodes/jkqtmathtextwhitespacenode.h @@ -0,0 +1,115 @@ +/* + Copyright (c) 2008-2022 Jan W. Krieger () + 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 . +*/ + + + + +#ifndef JKQTMATHTEXTWHITESPACENODE_H +#define JKQTMATHTEXTWHITESPACENODE_H +#include "jkqtmathtext/jkqtmathtext_imexport.h" +#include "jkqtmathtext/jkqtmathtexttools.h" +#include "jkqtmathtext/nodes/jkqtmathtextnode.h" +#include + +class JKQTMathText; // forward + + +/** \brief subclass representing one whitepsace node in the syntax tree + * \ingroup jkqtmathtext_items + * + * It can represent different types of spaces, see Types and different multiples of that space. + * so \c JKQTMathTextWhitespaceNode(WST1em,2,parent) will represent two 1em wide spaces, i.e. a 2em space. + */ +class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextWhitespaceNode: public JKQTMathTextNode { + public: + enum Types { + WSTNormal, /*!< \brief a normal-width whitespace */ + WSTNonbreaking, /*!< \brief a normal-width, non-breaking whitespace */ + WST1en, /*!< \brief 1en (= 0.5 * pointsize of the font) whitespace */ + WST1em, /*!< \brief 1em (= pointsize of the font) whitespace */ + WSTQuad=WST1em, /*!< \copydoc WST1em */ + WSThair, /*!< \brief hair (thinner than thin) whitespace (1/12 em = pointsize/12) */ + WSTthin, /*!< \brief thin whitespace (1/6 em = pointsize/6) */ + WSTnegthin, /*!< \brief negative thin whitespace (-1/6 em = -pointsize/6) */ + WSTmedium, /*!< \brief medium whitespace (2/9 em = pointsize*2/9) */ + WSTnegmedium, /*!< \brief negative medium whitespace (-2/9 em = -pointsize*2/9) */ + WSTthick, /*!< \brief thick whitespace (5/18 em = pointsize*5/18) */ + WSTnegthick, /*!< \brief negative thick whitespace (-5/18 em = -pointsize*5/18) */ + WSTthicker, /*!< \brief thicker whitespace (1/3 em = pointsize/3) */ + + }; + /** \brief converts Types \a type into a string */ + static QString Type2String(Types type); + /** \brief converts Types \a type into its width in points (pt), based on \a currentEv */ + double Type2PointWidth(Types type, JKQTMathTextEnvironment currentEv) const; + /** \brief checks whether a given LaTeX instruction name is supported by this node class type */ + static bool supportsInstructionName(const QString& instruction); + /** \brief constructs a node with count=1 and type=WSTNormal */ + explicit JKQTMathTextWhitespaceNode(JKQTMathText* parent); + /** \brief constructs a node with count=1 and the width derived from the instruction name \a type */ + explicit JKQTMathTextWhitespaceNode(const QString& type, JKQTMathText* parent); + /** \brief constructs a node with the specified \a count and the width derived from the instruction name \a type */ + explicit JKQTMathTextWhitespaceNode(const QString& type, size_t count, JKQTMathText* parent); + /** \brief constructs a node with count=1 and the given \a type */ + explicit JKQTMathTextWhitespaceNode(Types type, JKQTMathText* parent); + /** \brief constructs a node with the given \a type and \a count */ + explicit JKQTMathTextWhitespaceNode(Types type, size_t cound, 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; + /** \brief copydoc WhitespaceProps::type */ + Types getWhitespaceType() const; + /** \brief copydoc WhitespaceProps::count */ + size_t getWhitespaceCount() const; + /** \copydoc JKQTMathTextNode::draw() */ + virtual double draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSize=nullptr) 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 describes a whitespace */ + struct WhitespaceProps { + WhitespaceProps(Types type=WSTNormal, size_t count=1); + /** \brief type of the whitespace represented by this node */ + Types type; + /** \brief number of whitespaces of the given type, represented by this node (default: 1) */ + size_t count; + }; + /** \brief properties of the whitespace represented by this node */ + WhitespaceProps whitespace; + /** \brief converts Types \a type into its HTML representation */ + static QString Type2HTML(Types type); + /** \brief translation table between latex instruction and WhitespaceProps */ + static QHash supportedInstructions; + /** \brief initializes supportedInstructions */ + static void fillSupportedInstructions(); +}; + +#endif // JKQTMATHTEXTWHITESPACENODE_H + + + + + + + + +