made more STATIC data members thread_local or secured them by a std::mutex. This was at least JKQTMathText and JKQTBasePlotter should be usable in several threads

This commit is contained in:
jkriege2 2023-06-30 13:52:17 +02:00
parent 79d8dbad84
commit 3fc8951851
19 changed files with 133 additions and 48 deletions

View File

@ -38,6 +38,7 @@ const int JKQTPImageTools::LUTSIZE = 256;
QMap<int, JKQTPImageTools::LUTData > JKQTPImageTools::global_jkqtpimagetools_lutstore = JKQTPImageTools::getDefaultLUTs(); QMap<int, JKQTPImageTools::LUTData > JKQTPImageTools::global_jkqtpimagetools_lutstore = JKQTPImageTools::getDefaultLUTs();
int JKQTPImageTools::global_next_userpalette = JKQTPMathImageFIRST_REGISTERED_USER_PALETTE; int JKQTPImageTools::global_next_userpalette = JKQTPMathImageFIRST_REGISTERED_USER_PALETTE;
std::mutex JKQTPImageTools::lutMutex = std::mutex();
@ -2648,6 +2649,7 @@ bool JKQTPImagePlot_QPairCompareFirst(const QPair<T1, T2> &s1, const QPair<T1, T
} }
QStringList JKQTPImageTools::getPredefinedPalettes() { QStringList JKQTPImageTools::getPredefinedPalettes() {
std::lock_guard<std::mutex> lock(JKQTPImageTools::lutMutex);
static QStringList sl; static QStringList sl;
if (sl.size()!=JKQTPImageTools::global_jkqtpimagetools_lutstore.size()) { if (sl.size()!=JKQTPImageTools::global_jkqtpimagetools_lutstore.size()) {
@ -2665,6 +2667,7 @@ QStringList JKQTPImageTools::getPredefinedPalettes() {
QStringList JKQTPImageTools::getPredefinedPalettesMachineReadable() { QStringList JKQTPImageTools::getPredefinedPalettesMachineReadable() {
std::lock_guard<std::mutex> lock(JKQTPImageTools::lutMutex);
static QStringList sl; static QStringList sl;
if (sl.size()!=JKQTPImageTools::global_jkqtpimagetools_lutstore.size()) { if (sl.size()!=JKQTPImageTools::global_jkqtpimagetools_lutstore.size()) {
@ -2686,6 +2689,7 @@ QStringList JKQTPImageTools::getPredefinedPalettesMachineReadable() {
QString JKQTPImageTools::JKQTPMathImageColorPalette2String(JKQTPMathImageColorPalette p) QString JKQTPImageTools::JKQTPMathImageColorPalette2String(JKQTPMathImageColorPalette p)
{ {
std::lock_guard<std::mutex> lock(JKQTPImageTools::lutMutex);
auto it=JKQTPImageTools::global_jkqtpimagetools_lutstore.find(p); auto it=JKQTPImageTools::global_jkqtpimagetools_lutstore.find(p);
if (it==JKQTPImageTools::global_jkqtpimagetools_lutstore.end()) return QString::number(static_cast<int>(p)); if (it==JKQTPImageTools::global_jkqtpimagetools_lutstore.end()) return QString::number(static_cast<int>(p));
else { else {
@ -2696,6 +2700,7 @@ QString JKQTPImageTools::JKQTPMathImageColorPalette2String(JKQTPMathImageColorPa
JKQTPMathImageColorPalette JKQTPImageTools::String2JKQTPMathImageColorPalette(const QString &p) JKQTPMathImageColorPalette JKQTPImageTools::String2JKQTPMathImageColorPalette(const QString &p)
{ {
std::lock_guard<std::mutex> lock(JKQTPImageTools::lutMutex);
for (auto it=JKQTPImageTools::global_jkqtpimagetools_lutstore.begin(); it!=JKQTPImageTools::global_jkqtpimagetools_lutstore.end(); ++it) { for (auto it=JKQTPImageTools::global_jkqtpimagetools_lutstore.begin(); it!=JKQTPImageTools::global_jkqtpimagetools_lutstore.end(); ++it) {
if (QString::compare(p, it.value().name, Qt::CaseInsensitive)==0) { if (QString::compare(p, it.value().name, Qt::CaseInsensitive)==0) {
return static_cast<JKQTPMathImageColorPalette>(it.key()); return static_cast<JKQTPMathImageColorPalette>(it.key());
@ -2807,6 +2812,7 @@ QIcon JKQTPImageTools::GetPaletteIcon(JKQTPMathImageColorPalette palette) {
int JKQTPImageTools::registerPalette(const QString &name, const JKQTPImageTools::LUTType &paletteLut, const QString &nameT) int JKQTPImageTools::registerPalette(const QString &name, const JKQTPImageTools::LUTType &paletteLut, const QString &nameT)
{ {
std::lock_guard<std::mutex> lock(JKQTPImageTools::lutMutex);
int id=JKQTPImageTools::global_next_userpalette++; int id=JKQTPImageTools::global_next_userpalette++;
JKQTPImageTools::global_jkqtpimagetools_lutstore[id].name=name; JKQTPImageTools::global_jkqtpimagetools_lutstore[id].name=name;
JKQTPImageTools::global_jkqtpimagetools_lutstore[id].nameT=((nameT.size()>0)?nameT:name); JKQTPImageTools::global_jkqtpimagetools_lutstore[id].nameT=((nameT.size()>0)?nameT:name);

View File

@ -28,6 +28,7 @@
#include <cfloat> #include <cfloat>
#include <stdint.h> #include <stdint.h>
#include <QColor> #include <QColor>
#include <mutex>
#include <vector> #include <vector>
#include "jkqtcommon/jkqtcommon_imexport.h" #include "jkqtcommon/jkqtcommon_imexport.h"
#include "jkqtcommon/jkqtpmathtools.h" #include "jkqtcommon/jkqtpmathtools.h"
@ -482,6 +483,9 @@ struct JKQTPImageTools {
\see registerPalette() registerPalettesFromFile() \see registerPalette() registerPalettesFromFile()
*/ */
static JKQTCOMMON_LIB_EXPORT int global_next_userpalette; static JKQTCOMMON_LIB_EXPORT int global_next_userpalette;
/** \brief Mutex to protect global_jkqtpimagetools_lutstore and global_next_userpalette */
static JKQTCOMMON_LIB_EXPORT std::mutex lutMutex;
/*! \brief returns data of the default LUTs, used to initialize global_jkqtpimagetools_lutstore /*! \brief returns data of the default LUTs, used to initialize global_jkqtpimagetools_lutstore
\internal \internal

View File

@ -23,15 +23,15 @@
#include <QApplication> #include <QApplication>
namespace JKQTPAutoOutputTimer_private {
thread_local int global_indent=0;
int JKQTPAutoOutputTimer::global_indent=0; }
JKQTPAutoOutputTimer::JKQTPAutoOutputTimer(const QString& _message) : JKQTPAutoOutputTimer::JKQTPAutoOutputTimer(const QString& _message) :
QElapsedTimer(),message(_message),indent() QElapsedTimer(),message(_message),indent()
{ {
this->indent=QString(global_indent, QLatin1Char(' ')); this->indent=QString(JKQTPAutoOutputTimer_private::global_indent, QLatin1Char(' '));
global_indent+=4; JKQTPAutoOutputTimer_private::global_indent+=4;
#if QT_VERSION >= 0x040800 #if QT_VERSION >= 0x040800
qDebug()<<this->indent<<"TIMER_START: "<<message; qDebug()<<this->indent<<"TIMER_START: "<<message;
#else #else
@ -47,7 +47,7 @@ JKQTPAutoOutputTimer::~JKQTPAutoOutputTimer()
#else #else
qDebug()<<this->indent<<"TIMER_END: "<<message<<" DUR: "<<double(elapsed())/1.0e3<<"ms"; qDebug()<<this->indent<<"TIMER_END: "<<message<<" DUR: "<<double(elapsed())/1.0e3<<"ms";
#endif #endif
global_indent-=4; JKQTPAutoOutputTimer_private::global_indent-=4;
} }

View File

@ -62,7 +62,7 @@ class JKQTCOMMON_LIB_EXPORT JKQTPAutoOutputTimer : public QElapsedTimer
protected: protected:
QString message; QString message;
QString indent; QString indent;
static int global_indent;
}; };

View File

@ -523,7 +523,7 @@ static const struct RGBData {
static const int rgbTblSize = sizeof(rgbTbl) / sizeof(RGBData); static const int rgbTblSize = sizeof(rgbTbl) / sizeof(RGBData);
const QStringList& jkqtp_listNamedColors() { const QStringList& jkqtp_listNamedColors() {
static QStringList sl; thread_local QStringList sl;
if (sl.size()==0) { if (sl.size()==0) {
sl.reserve(rgbTblSize); sl.reserve(rgbTblSize);
for (int i=0; i<rgbTblSize; i++) { for (int i=0; i<rgbTblSize; i++) {

View File

@ -46,6 +46,7 @@
#include <QFontMetricsF> #include <QFontMetricsF>
#include <QDebug> #include <QDebug>
#include <QFontDatabase> #include <QFontDatabase>
#include <mutex>
#include <typeinfo> #include <typeinfo>
#include <QPainterPath> #include <QPainterPath>
@ -63,6 +64,7 @@ QString JKQTMathText::init_caligraphicFont="decorative";
QString JKQTMathText::init_blackboardFont="blackboard"; QString JKQTMathText::init_blackboardFont="blackboard";
QString JKQTMathText::init_fracturFont="fraktur"; QString JKQTMathText::init_fracturFont="fraktur";
bool JKQTMathText::s_firstStart=true; bool JKQTMathText::s_firstStart=true;
std::mutex JKQTMathText::s_mutex=std::mutex();
@ -126,7 +128,7 @@ JKQTMathText::JKQTMathText(QObject* parent, bool useFontsForGUI):
std::lock_guard<std::mutex> lock(s_mutex);
if (s_firstStart) { if (s_firstStart) {
//t0=std::chrono::high_resolution_clock::now(); //t0=std::chrono::high_resolution_clock::now();

View File

@ -40,6 +40,7 @@
#include <QPixmap> #include <QPixmap>
#include <type_traits> #include <type_traits>
#include <memory> #include <memory>
#include <mutex>
class JKQTMathTextNode; // forward class JKQTMathTextNode; // forward
@ -1069,6 +1070,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
static QString init_fracturFont; static QString init_fracturFont;
/** \brief used to check for the first construction of a JKQTMathText ... if \c true several static variables are initialized in the constructor */ /** \brief used to check for the first construction of a JKQTMathText ... if \c true several static variables are initialized in the constructor */
static bool s_firstStart; static bool s_firstStart;
/** \brief mutex to protect the static members */
static std::mutex s_mutex;
}; };

View File

@ -21,7 +21,6 @@
#include "jkqtmathtext/jkqtmathtexttools.h" #include "jkqtmathtext/jkqtmathtexttools.h"
#include "jkqtmathtext/jkqtmathtext.h" #include "jkqtmathtext/jkqtmathtext.h"
#include "jkqtcommon/jkqtpcodestructuring.h"
#include "jkqtcommon/jkqtpstringtools.h" #include "jkqtcommon/jkqtpstringtools.h"
#include <cmath> #include <cmath>
#include <QFontMetricsF> #include <QFontMetricsF>
@ -35,6 +34,8 @@
void initJKQTMathTextResources() void initJKQTMathTextResources()
{ {
static bool initialized=false; static bool initialized=false;
static std::mutex mutex_initialized;
std::lock_guard<std::mutex> lock(mutex_initialized);
if (!initialized) { if (!initialized) {
#ifdef JKQTMATHTEXT_COMPILED_WITH_XITS #ifdef JKQTMATHTEXT_COMPILED_WITH_XITS
Q_INIT_RESOURCE(xits); Q_INIT_RESOURCE(xits);
@ -249,6 +250,8 @@ JKQTMathTextFontSpecifier JKQTMathTextFontSpecifier::getXITSFamilies()
} }
static JKQTMathTextFontSpecifier fontSpec; static JKQTMathTextFontSpecifier fontSpec;
static std::mutex fontSpecMutex;
std::lock_guard<std::mutex> lock(fontSpecMutex);
if (fontSpec.m_fontName.isEmpty() && fontSpec.m_mathFontName.isEmpty()) { if (fontSpec.m_fontName.isEmpty() && fontSpec.m_mathFontName.isEmpty()) {
fontSpec.m_transformOnOutput=false; fontSpec.m_transformOnOutput=false;
for (int i=0; i<fontFamilies.size(); i++) { for (int i=0; i<fontFamilies.size(); i++) {
@ -287,6 +290,8 @@ JKQTMathTextFontSpecifier JKQTMathTextFontSpecifier::getASANAFamilies()
static JKQTMathTextFontSpecifier fontSpec; static JKQTMathTextFontSpecifier fontSpec;
static std::mutex fontSpecMutex;
std::lock_guard<std::mutex> lock(fontSpecMutex);
if (fontSpec.m_fontName.isEmpty() && fontSpec.m_mathFontName.isEmpty()) { if (fontSpec.m_fontName.isEmpty() && fontSpec.m_mathFontName.isEmpty()) {
fontSpec.m_transformOnOutput=false; fontSpec.m_transformOnOutput=false;
for (int i=0; i<fontFamilies.size(); i++) { for (int i=0; i<fontFamilies.size(); i++) {
@ -318,6 +323,8 @@ JKQTMathTextFontSpecifier JKQTMathTextFontSpecifier::getSTIXFamilies()
static QStringList textNames{"STIX", "STIXGeneral", "STIX General"}; static QStringList textNames{"STIX", "STIXGeneral", "STIX General"};
static JKQTMathTextFontSpecifier fontSpec; static JKQTMathTextFontSpecifier fontSpec;
static std::mutex fontSpecMutex;
std::lock_guard<std::mutex> lock(fontSpecMutex);
if (fontSpec.m_fontName.isEmpty() && fontSpec.m_mathFontName.isEmpty()) { if (fontSpec.m_fontName.isEmpty() && fontSpec.m_mathFontName.isEmpty()) {
fontSpec.m_transformOnOutput=false; fontSpec.m_transformOnOutput=false;
#if (QT_VERSION<QT_VERSION_CHECK(6, 0, 0)) #if (QT_VERSION<QT_VERSION_CHECK(6, 0, 0))
@ -376,6 +383,8 @@ JKQTMathTextFontSpecifier JKQTMathTextFontSpecifier::getFIRAFamilies()
} }
static JKQTMathTextFontSpecifier fontSpec; static JKQTMathTextFontSpecifier fontSpec;
static std::mutex fontSpecMutex;
std::lock_guard<std::mutex> lock(fontSpecMutex);
if (fontSpec.m_fontName.isEmpty() && fontSpec.m_mathFontName.isEmpty()) { if (fontSpec.m_fontName.isEmpty() && fontSpec.m_mathFontName.isEmpty()) {
fontSpec.m_transformOnOutput=false; fontSpec.m_transformOnOutput=false;
for (int i=0; i<fontFamilies.size(); i++) { for (int i=0; i<fontFamilies.size(); i++) {
@ -404,6 +413,8 @@ JKQTMathTextFontSpecifier JKQTMathTextFontSpecifier::getFIRAFamilies()
JKQTMathTextFontSpecifier JKQTMathTextFontSpecifier::getAppFontFamilies() JKQTMathTextFontSpecifier JKQTMathTextFontSpecifier::getAppFontFamilies()
{ {
static JKQTMathTextFontSpecifier fontSpec; static JKQTMathTextFontSpecifier fontSpec;
static std::mutex fontSpecMutex;
std::lock_guard<std::mutex> lock(fontSpecMutex);
if (fontSpec.m_fontName.isEmpty() && fontSpec.m_mathFontName.isEmpty()) { if (fontSpec.m_fontName.isEmpty() && fontSpec.m_mathFontName.isEmpty()) {
#if (QT_VERSION<QT_VERSION_CHECK(6, 0, 0)) #if (QT_VERSION<QT_VERSION_CHECK(6, 0, 0))
QFontDatabase fdb; QFontDatabase fdb;
@ -444,6 +455,8 @@ JKQTMathTextFontSpecifier JKQTMathTextFontSpecifier::getAppFontFamilies()
JKQTMathTextFontSpecifier JKQTMathTextFontSpecifier::getAppFontSFFamilies() JKQTMathTextFontSpecifier JKQTMathTextFontSpecifier::getAppFontSFFamilies()
{ {
static JKQTMathTextFontSpecifier fontSpec; static JKQTMathTextFontSpecifier fontSpec;
static std::mutex fontSpecMutex;
std::lock_guard<std::mutex> lock(fontSpecMutex);
if (fontSpec.m_fontName.isEmpty() && fontSpec.m_mathFontName.isEmpty()) { if (fontSpec.m_fontName.isEmpty() && fontSpec.m_mathFontName.isEmpty()) {
const QFont f=QGuiApplication::font().family(); const QFont f=QGuiApplication::font().family();
QFont testFnt; QFont testFnt;
@ -927,8 +940,8 @@ bool JKQTMathTextTBRDataH::operator==(const JKQTMathTextTBRDataH &other) const
QRectF JKQTMathTextGetTightBoundingRect(const QFont &fm, const QString &text, QPaintDevice *pd) QRectF JKQTMathTextGetTightBoundingRect(const QFont &fm, const QString &text, QPaintDevice *pd)
{ {
static QList<JKQTMathTextTBRData> JKQTMathText_tbrs=QList<JKQTMathTextTBRData>(); thread_local QList<JKQTMathTextTBRData> JKQTMathText_tbrs=QList<JKQTMathTextTBRData>();
static QHash<JKQTMathTextTBRDataH, QRectF> JKQTMathText_tbrh=QHash<JKQTMathTextTBRDataH, QRectF>(); thread_local QHash<JKQTMathTextTBRDataH, QRectF> JKQTMathText_tbrh=QHash<JKQTMathTextTBRDataH, QRectF>();
JKQTMathTextTBRDataH dh(fm, text, pd); JKQTMathTextTBRDataH dh(fm, text, pd);
if (pd) { if (pd) {

View File

@ -169,6 +169,9 @@ QHash<QString, JKQTMathTextBoxInstructionNode::InstructionProperties> JKQTMathTe
void JKQTMathTextBoxInstructionNode::fillInstructions() void JKQTMathTextBoxInstructionNode::fillInstructions()
{ {
static std::mutex sMutex;
std::lock_guard<std::mutex> lock(sMutex);
if (instructions.size()>0) return;
{ {
InstructionProperties i(InstructionProperties::NoModification, InstructionProperties i(InstructionProperties::NoModification,

View File

@ -172,6 +172,8 @@ QHash<QString, JKQTMathTextDecoratedNode::DecorationType> JKQTMathTextDecoratedN
void JKQTMathTextDecoratedNode::fillInstructions() void JKQTMathTextDecoratedNode::fillInstructions()
{ {
static std::mutex sMutex;
std::lock_guard<std::mutex> lock(sMutex);
if (instructions.size()>0) return; if (instructions.size()>0) return;
instructions["vec"]=MTDvec; instructions["vec"]=MTDvec;

View File

@ -39,6 +39,8 @@ QHash<QString, JKQTMathTextFracNode::FracType> JKQTMathTextFracNode::instruction
void JKQTMathTextFracNode::fillInstructions() void JKQTMathTextFracNode::fillInstructions()
{ {
static std::mutex sMutex;
std::lock_guard<std::mutex> lock(sMutex);
if (instructions.size()>0) return; if (instructions.size()>0) return;
instructions["frac"]=MTFMfrac; instructions["frac"]=MTFMfrac;
instructions["dfrac"] = MTFMdfrac; instructions["dfrac"] = MTFMdfrac;

View File

@ -144,6 +144,9 @@ QHash<QString, JKQTMathTextSimpleInstructionNode::InstructionProperties> JKQTMat
void JKQTMathTextSimpleInstructionNode::fillInstructions() void JKQTMathTextSimpleInstructionNode::fillInstructions()
{ {
static std::mutex sMutex;
std::lock_guard<std::mutex> lock(sMutex);
if (instructions.size()>0) return;
{ {
InstructionProperties i([](const QStringList& parameters) -> QString { InstructionProperties i([](const QStringList& parameters) -> QString {
bool ok=false; bool ok=false;

View File

@ -116,6 +116,9 @@ QHash<QString, JKQTMathTextModifiedTextPropsInstructionNode::InstructionProperti
void JKQTMathTextModifiedTextPropsInstructionNode::fillInstructions() void JKQTMathTextModifiedTextPropsInstructionNode::fillInstructions()
{ {
static std::mutex sMutex;
std::lock_guard<std::mutex> lock(sMutex);
if (instructions.size()>0) return;
{ {
InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& /*parameters*/) { InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& /*parameters*/) {
ev.bold=false; ev.bold=false;
@ -534,6 +537,9 @@ QHash<QString, JKQTMathTextModifiedEnvironmentInstructionNode::InstructionProper
void JKQTMathTextModifiedEnvironmentInstructionNode::fillInstructions() void JKQTMathTextModifiedEnvironmentInstructionNode::fillInstructions()
{ {
static std::mutex sMutex;
std::lock_guard<std::mutex> lock(sMutex);
if (instructions.size()>0) return;
{ {
InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& /*parameters*/, const JKQTMathText* parentMathText) { InstructionProperties i([](JKQTMathTextEnvironment& ev, const QStringList& /*parameters*/, const JKQTMathText* parentMathText) {

View File

@ -491,6 +491,8 @@ QHash<QString, JKQTMathTextSymbolNode::SymbolFullProps> JKQTMathTextSymbolNode::
void JKQTMathTextSymbolNode::fillSymbolTables() void JKQTMathTextSymbolNode::fillSymbolTables()
{ {
static std::mutex sMutex;
std::lock_guard<std::mutex> lock(sMutex);
if (symbols.size()>0) return; // tables have already been filled! So nothing to do here if (symbols.size()>0) return; // tables have already been filled! So nothing to do here
/************************************************************************************** /**************************************************************************************

View File

@ -76,15 +76,10 @@ bool JKQTMathTextTextBaseNode::toHtml(QString &html, JKQTMathTextEnvironment cur
QHash<QChar, uint32_t> JKQTMathTextTextNode::blackboardUnicodeTable=QHash<QChar, uint32_t>(); QHash<QChar, uint32_t> JKQTMathTextTextNode::blackboardUnicodeTable=QHash<QChar, uint32_t>();
void JKQTMathTextTextNode::fillStaticTables() { void JKQTMathTextTextNode::fillStaticTables() {
static std::mutex sMutex;
std::lock_guard<std::mutex> lock(sMutex);
if (blackboardUnicodeTable.size()>0) return; if (blackboardUnicodeTable.size()>0) return;
blackboardUnicodeTable['C']=0x2102;
blackboardUnicodeTable['H']=0x210D;
blackboardUnicodeTable['N']=0x2115;
blackboardUnicodeTable['P']=0x2119;
blackboardUnicodeTable['Q']=0x211A;
blackboardUnicodeTable['R']=0x211D;
blackboardUnicodeTable['Z']=0x2124;
for (const QChar ch: QString("ABDEFGIJKLMOSTUVWXYZ")) { for (const QChar ch: QString("ABDEFGIJKLMOSTUVWXYZ")) {
blackboardUnicodeTable[ch]=0x1D538+(ch.unicode()-QChar('A').unicode()); blackboardUnicodeTable[ch]=0x1D538+(ch.unicode()-QChar('A').unicode());
@ -95,6 +90,14 @@ void JKQTMathTextTextNode::fillStaticTables() {
for (const QChar ch: QString("0123456789")) { for (const QChar ch: QString("0123456789")) {
blackboardUnicodeTable[ch]=0x1D7D8+(ch.unicode()-QChar('0').unicode()); blackboardUnicodeTable[ch]=0x1D7D8+(ch.unicode()-QChar('0').unicode());
} }
blackboardUnicodeTable['C']=0x2102;
blackboardUnicodeTable['H']=0x210D;
blackboardUnicodeTable['N']=0x2115;
blackboardUnicodeTable['P']=0x2119;
blackboardUnicodeTable['Q']=0x211A;
blackboardUnicodeTable['R']=0x211D;
blackboardUnicodeTable['Z']=0x2124;
} }
JKQTMathTextTextNode::JKQTMathTextTextNode(JKQTMathText* _parent, const QString& textIn, bool addWhitespace, bool stripInnerWhitepace): JKQTMathTextTextNode::JKQTMathTextTextNode(JKQTMathText* _parent, const QString& textIn, bool addWhitespace, bool stripInnerWhitepace):

View File

@ -138,6 +138,8 @@ QHash<QString, JKQTMathTextWhitespaceNode::WhitespaceProps> JKQTMathTextWhitespa
void JKQTMathTextWhitespaceNode::fillSupportedInstructions() void JKQTMathTextWhitespaceNode::fillSupportedInstructions()
{ {
static std::mutex sMutex;
std::lock_guard<std::mutex> lock(sMutex);
if (supportedInstructions.size()==0) { if (supportedInstructions.size()==0) {
supportedInstructions[" "]=WhitespaceProps(WSTthicker, 1); supportedInstructions[" "]=WhitespaceProps(WSTthicker, 1);
supportedInstructions["nbsp"]=WhitespaceProps(WSTNonbreaking, 1); supportedInstructions["nbsp"]=WhitespaceProps(WSTNonbreaking, 1);
@ -427,6 +429,9 @@ QHash<QString, JKQTMathTextPhantomNode::Mode> JKQTMathTextPhantomNode::instructi
void JKQTMathTextPhantomNode::fillInstructions() void JKQTMathTextPhantomNode::fillInstructions()
{ {
static std::mutex sMutex;
std::lock_guard<std::mutex> lock(sMutex);
if (instructions.size()>0) return;
instructions["phantom"] = FMwidthAndHeight; instructions["phantom"] = FMwidthAndHeight;
instructions["hphantom"] = FMwidth; instructions["hphantom"] = FMwidth;
instructions["vphantom"] = FMheight; instructions["vphantom"] = FMheight;

View File

@ -60,6 +60,8 @@ QHash<QString,double> JKQTMathTextLatexParser::big_instructions_family;
// define some static sets for easy character lookup/identificattion // define some static sets for easy character lookup/identificattion
void JKQTMathTextLatexParser::initStaticStructures() void JKQTMathTextLatexParser::initStaticStructures()
{ {
static std::mutex sMutex;
std::lock_guard<std::mutex> lock(sMutex);
if (accentLetters.size()==0) { if (accentLetters.size()==0) {
auto fAddUml=[](const QString& cmd, const QChar& letter, const QChar& ch) { auto fAddUml=[](const QString& cmd, const QChar& letter, const QChar& ch) {
QString i; QString i;

View File

@ -53,15 +53,18 @@
#include "jkqtmathtext/jkqtmathtext.h" #include "jkqtmathtext/jkqtmathtext.h"
#include <algorithm> #include <algorithm>
static QString globalUserSettigsFilename=""; QString JKQTBasePlotter::globalUserSettigsFilename="";
static QString globalUserSettigsPrefix=""; QString JKQTBasePlotter::globalUserSettigsPrefix="";
static QList<JKQTPPaintDeviceAdapter*> jkqtpPaintDeviceAdapters; std::mutex JKQTBasePlotter::globalUserSettingsMutex = std::mutex();
static QList<JKQTPSaveDataAdapter*> jkqtpSaveDataAdapters; JKQTPSynchronized<QList<JKQTPPaintDeviceAdapter*>> JKQTBasePlotter::jkqtpPaintDeviceAdapters;
JKQTPSynchronized<QList<JKQTPSaveDataAdapter*>> JKQTBasePlotter::jkqtpSaveDataAdapters;
void initJKQTBasePlotterResources() void initJKQTBasePlotterResources()
{ {
static std::mutex sMutex;
std::lock_guard<std::mutex> lock(sMutex);
Q_INIT_RESOURCE(jkqtpbaseplotter); Q_INIT_RESOURCE(jkqtpbaseplotter);
initJKQTMathTextResources(); initJKQTMathTextResources();
} }
@ -69,30 +72,34 @@ void initJKQTBasePlotterResources()
void JKQTBasePlotter::setDefaultJKQTBasePrinterUserSettings(QString userSettigsFilename, const QString& userSettigsPrefix) void JKQTBasePlotter::setDefaultJKQTBasePrinterUserSettings(QString userSettigsFilename, const QString& userSettigsPrefix)
{ {
std::lock_guard<std::mutex> lock(globalUserSettingsMutex);
globalUserSettigsFilename=userSettigsFilename; globalUserSettigsFilename=userSettigsFilename;
globalUserSettigsPrefix=userSettigsPrefix; globalUserSettigsPrefix=userSettigsPrefix;
} }
void JKQTBasePlotter::registerPaintDeviceAdapter(JKQTPPaintDeviceAdapter *adapter) void JKQTBasePlotter::registerPaintDeviceAdapter(JKQTPPaintDeviceAdapter *adapter)
{ {
jkqtpPaintDeviceAdapters.append(adapter); JKQTPSynchronized<QList<JKQTPPaintDeviceAdapter*>>::Locker lock(jkqtpPaintDeviceAdapters);
jkqtpPaintDeviceAdapters.get().append(adapter);
} }
void JKQTBasePlotter::deregisterPaintDeviceAdapter(JKQTPPaintDeviceAdapter *adapter) void JKQTBasePlotter::deregisterPaintDeviceAdapter(JKQTPPaintDeviceAdapter *adapter)
{ {
if (jkqtpPaintDeviceAdapters.contains(adapter)) jkqtpPaintDeviceAdapters.removeAll(adapter); JKQTPSynchronized<QList<JKQTPPaintDeviceAdapter*>>::Locker lock(jkqtpPaintDeviceAdapters);
if (jkqtpPaintDeviceAdapters.get().contains(adapter)) jkqtpPaintDeviceAdapters.get().removeAll(adapter);
} }
bool JKQTBasePlotter::registerSaveDataAdapter(JKQTPSaveDataAdapter *adapter) bool JKQTBasePlotter::registerSaveDataAdapter(JKQTPSaveDataAdapter *adapter)
{ {
if (adapter){ if (adapter){
JKQTPSynchronized<QList<JKQTPSaveDataAdapter*>>::Locker lock(jkqtpSaveDataAdapters);
QString format=adapter->getFilter(); QString format=adapter->getFilter();
for (int i=0; i<jkqtpSaveDataAdapters.size(); i++) { for (int i=0; i<jkqtpSaveDataAdapters.get().size(); i++) {
if (jkqtpSaveDataAdapters[i] && jkqtpSaveDataAdapters[i]->getFilter()==format) { if (jkqtpSaveDataAdapters.get()[i] && jkqtpSaveDataAdapters.get()[i]->getFilter()==format) {
return false; return false;
} }
} }
jkqtpSaveDataAdapters.append(adapter); jkqtpSaveDataAdapters.get().append(adapter);
return true; return true;
} }
return false; return false;
@ -100,10 +107,16 @@ bool JKQTBasePlotter::registerSaveDataAdapter(JKQTPSaveDataAdapter *adapter)
bool JKQTBasePlotter::deregisterSaveDataAdapter(JKQTPSaveDataAdapter *adapter) bool JKQTBasePlotter::deregisterSaveDataAdapter(JKQTPSaveDataAdapter *adapter)
{ {
if (jkqtpSaveDataAdapters.contains(adapter)) jkqtpSaveDataAdapters.removeAll(adapter); JKQTPSynchronized<QList<JKQTPSaveDataAdapter*>>::Locker lock(jkqtpSaveDataAdapters);
if (jkqtpSaveDataAdapters.get().contains(adapter)) jkqtpSaveDataAdapters.get().removeAll(adapter);
return true; return true;
} }
JKQTBasePlotter::textSizeData JKQTBasePlotter::getTextSizeDetail(const QFont &fm, const QString &text, QPainter& painter) JKQTBasePlotter::textSizeData JKQTBasePlotter::getTextSizeDetail(const QFont &fm, const QString &text, QPainter& painter)
{ {
return getTextSizeDetail(fm.family(), fm.pointSizeF(), text, painter); return getTextSizeDetail(fm.family(), fm.pointSizeF(), text, painter);
@ -111,6 +124,7 @@ JKQTBasePlotter::textSizeData JKQTBasePlotter::getTextSizeDetail(const QFont &fm
JKQTBasePlotter::textSizeData JKQTBasePlotter::getTextSizeDetail(const QString &fontName, double fontSize, const QString &text, QPainter& painter) JKQTBasePlotter::textSizeData JKQTBasePlotter::getTextSizeDetail(const QString &fontName, double fontSize, const QString &text, QPainter& painter)
{ {
thread_local QHash<JKQTBasePlotter::textSizeKey, JKQTBasePlotter::textSizeData> s_TextSizeDataCache;
JKQTBasePlotter::textSizeKey dh(fontName, fontSize, text, painter.device()); JKQTBasePlotter::textSizeKey dh(fontName, fontSize, text, painter.device());
if (s_TextSizeDataCache.contains(dh)) return s_TextSizeDataCache[dh]; if (s_TextSizeDataCache.contains(dh)) return s_TextSizeDataCache[dh];
JKQTBasePlotter::textSizeData d; JKQTBasePlotter::textSizeData d;
@ -185,8 +199,11 @@ JKQTBasePlotter::JKQTBasePlotter(bool datastore_internal, QObject* parent, JKQTP
lineWidthPrintMultiplier=1; lineWidthPrintMultiplier=1;
fontSizeMultiplier=1; fontSizeMultiplier=1;
lineWidthMultiplier=1; lineWidthMultiplier=1;
userSettigsFilename=globalUserSettigsFilename; {
userSettigsPrefix=globalUserSettigsPrefix; std::lock_guard<std::mutex> lock(globalUserSettingsMutex);
userSettigsFilename=globalUserSettigsFilename;
userSettigsPrefix=globalUserSettigsPrefix;
}
#ifndef JKQTPLOTTER_COMPILE_WITHOUT_PRINTSUPPORT #ifndef JKQTPLOTTER_COMPILE_WITHOUT_PRINTSUPPORT
currentPrinter=QPrinterInfo::defaultPrinter().printerName(); currentPrinter=QPrinterInfo::defaultPrinter().printerName();
#endif #endif
@ -3599,9 +3616,12 @@ void JKQTBasePlotter::saveData(const QString& filename, const QString &format) {
fileformats<<tr("Matlab Script (*.m)"); fileformats<<tr("Matlab Script (*.m)");
fileformatIDs<<"m"; fileformatIDs<<"m";
for (int i=0; i<jkqtpSaveDataAdapters.size(); i++) { {
fileformats<<jkqtpSaveDataAdapters[i]->getFilter(); JKQTPSynchronized<QList<JKQTPSaveDataAdapter*>>::Locker lock(jkqtpSaveDataAdapters);
fileformatIDs<<QString("custom%1").arg(i); for (int i=0; i<jkqtpSaveDataAdapters.get().size(); i++) {
fileformats<<jkqtpSaveDataAdapters.get()[i]->getFilter();
fileformatIDs<<QString("custom%1").arg(i);
}
} }
@ -3665,10 +3685,11 @@ void JKQTBasePlotter::saveData(const QString& filename, const QString &format) {
QString fidx=fmt; QString fidx=fmt;
fidx=fidx.remove(0,6); fidx=fidx.remove(0,6);
int idx=fidx.toInt(); int idx=fidx.toInt();
if (idx>=0 && idx<jkqtpSaveDataAdapters.size() && jkqtpSaveDataAdapters[idx]) { JKQTPSynchronized<QList<JKQTPSaveDataAdapter*>>::Locker lock(jkqtpSaveDataAdapters);
if (idx>=0 && idx<jkqtpSaveDataAdapters.get().size() && jkqtpSaveDataAdapters.get()[idx]) {
QStringList cn; QStringList cn;
QList<QVector<double> > dataset=datastore->getData(&cn); QList<QVector<double> > dataset=datastore->getData(&cn);
jkqtpSaveDataAdapters[idx]->saveJKQTPData(fn, dataset, cn); jkqtpSaveDataAdapters.get()[idx]->saveJKQTPData(fn, dataset, cn);
} }
} }
} }
@ -3849,8 +3870,11 @@ void JKQTBasePlotter::saveImage(const QString& filename, bool displayPreview) {
filt<<tr("TIFF Image [Qt] (*.tif *.tiff)"); filt<<tr("TIFF Image [Qt] (*.tif *.tiff)");
filt<<tr("JPEG Image [Qt] (*.jpg *.jpeg)"); filt<<tr("JPEG Image [Qt] (*.jpg *.jpeg)");
const int filtStartSize=filt.size(); const int filtStartSize=filt.size();
for (int i=0; i<jkqtpPaintDeviceAdapters.size(); i++) { {
filt<<jkqtpPaintDeviceAdapters[i]->getFilter(); JKQTPSynchronized<QList<JKQTPPaintDeviceAdapter*>>::Locker lock(jkqtpPaintDeviceAdapters);
for (int i=0; i<jkqtpPaintDeviceAdapters.get().size(); i++) {
filt<<jkqtpPaintDeviceAdapters.get()[i]->getFilter();
}
} }
int qtwritersidx=filt.size(); int qtwritersidx=filt.size();
QList<QByteArray> writerformats=QImageWriter::supportedImageFormats(); QList<QByteArray> writerformats=QImageWriter::supportedImageFormats();
@ -3874,12 +3898,14 @@ void JKQTBasePlotter::saveImage(const QString& filename, bool displayPreview) {
saveUserSettings(); saveUserSettings();
if (!fn.isEmpty()) { if (!fn.isEmpty()) {
int filtID=filt.indexOf(selFormat); int filtID=filt.indexOf(selFormat);
bool isWithSpecialDeviceAdapter=filtID>=filtStartSize && filtID<filtStartSize+jkqtpPaintDeviceAdapters.size(); JKQTPSynchronized<QList<JKQTPPaintDeviceAdapter*>>::Locker lock(jkqtpPaintDeviceAdapters);
bool isWithSpecialDeviceAdapter=filtID>=filtStartSize && filtID<filtStartSize+jkqtpPaintDeviceAdapters.get().size();
int adapterID=filtID-filtStartSize; int adapterID=filtID-filtStartSize;
QString e=QFileInfo(filename).suffix().toLower(); QString e=QFileInfo(filename).suffix().toLower();
if (!isWithSpecialDeviceAdapter) { if (!isWithSpecialDeviceAdapter) {
for (int i=0; i<jkqtpPaintDeviceAdapters.size(); i++) { for (int i=0; i<jkqtpPaintDeviceAdapters.get().size(); i++) {
if (jkqtpPaintDeviceAdapters[i]->getFileExtension().contains(e)) { if (jkqtpPaintDeviceAdapters.get()[i]->getFileExtension().contains(e)) {
adapterID=i; adapterID=i;
isWithSpecialDeviceAdapter=true; isWithSpecialDeviceAdapter=true;
break; break;
@ -3897,7 +3923,7 @@ void JKQTBasePlotter::saveImage(const QString& filename, bool displayPreview) {
return; return;
} }
#endif #endif
if (isWithSpecialDeviceAdapter && adapterID>=0 && adapterID<jkqtpPaintDeviceAdapters.size()) { if (isWithSpecialDeviceAdapter && adapterID>=0 && adapterID<jkqtpPaintDeviceAdapters.get().size()) {
QString tempFM=""; QString tempFM="";
if (QFile::exists(fn)) { if (QFile::exists(fn)) {
#ifdef QFWIDLIB_LIBRARY #ifdef QFWIDLIB_LIBRARY
@ -3916,10 +3942,10 @@ void JKQTBasePlotter::saveImage(const QString& filename, bool displayPreview) {
emit beforeExporting();; auto __finalpaint=JKQTPFinally([&]() { emit afterExporting();}); emit beforeExporting();; auto __finalpaint=JKQTPFinally([&]() { emit afterExporting();});
gridPrintingCalc(); gridPrintingCalc();
QPaintDevice* paintDevice=jkqtpPaintDeviceAdapters[adapterID]->createPaintdevice(fn, jkqtp_roundTo<int>(gridPrintingSize.width()), jkqtp_roundTo<int>(gridPrintingSize.height())); QPaintDevice* paintDevice=jkqtpPaintDeviceAdapters.get()[adapterID]->createPaintdevice(fn, jkqtp_roundTo<int>(gridPrintingSize.width()), jkqtp_roundTo<int>(gridPrintingSize.height()));
#ifndef JKQTPLOTTER_COMPILE_WITHOUT_PRINTSUPPORT #ifndef JKQTPLOTTER_COMPILE_WITHOUT_PRINTSUPPORT
if (!printpreviewNew(paintDevice, jkqtpPaintDeviceAdapters[adapterID]->getSetAbsolutePaperSize(), jkqtpPaintDeviceAdapters[adapterID]->getPrintSizeXInMM(), jkqtpPaintDeviceAdapters[adapterID]->getPrintSizeYInMM(), displayPreview)) { if (!printpreviewNew(paintDevice, jkqtpPaintDeviceAdapters.get()[adapterID]->getSetAbsolutePaperSize(), jkqtpPaintDeviceAdapters.get()[adapterID]->getPrintSizeXInMM(), jkqtpPaintDeviceAdapters.get()[adapterID]->getPrintSizeYInMM(), displayPreview)) {
delete paintDevice; delete paintDevice;
@ -3932,7 +3958,7 @@ void JKQTBasePlotter::saveImage(const QString& filename, bool displayPreview) {
{ {
#endif #endif
delete paintDevice; delete paintDevice;
paintDevice=jkqtpPaintDeviceAdapters[adapterID]->createPaintdeviceMM(fn,printSizeX_Millimeter,printSizeY_Millimeter); paintDevice=jkqtpPaintDeviceAdapters.get()[adapterID]->createPaintdeviceMM(fn,printSizeX_Millimeter,printSizeY_Millimeter);
printpreviewPaintRequestedNewPaintDevice(paintDevice); printpreviewPaintRequestedNewPaintDevice(paintDevice);
delete paintDevice; delete paintDevice;
} }
@ -5299,7 +5325,6 @@ void JKQTBasePlotter::setEmittingSignalsEnabled(bool enabled)
} }
QHash<JKQTBasePlotter::textSizeKey, JKQTBasePlotter::textSizeData> JKQTBasePlotter::s_TextSizeDataCache=QHash<JKQTBasePlotter::textSizeKey, JKQTBasePlotter::textSizeData>();
JKQTBasePlotter::textSizeKey::textSizeKey(const QFont &f, const QString &text, QPaintDevice *pd): JKQTBasePlotter::textSizeKey::textSizeKey(const QFont &f, const QString &text, QPaintDevice *pd):
text(), f(), ldpiX(0), ldpiY(0), pdpiX(0), pdpiY(0) text(), f(), ldpiX(0), ldpiY(0), pdpiX(0), pdpiY(0)

View File

@ -28,6 +28,7 @@
#include "jkqtmathtext/jkqtmathtext.h" #include "jkqtmathtext/jkqtmathtext.h"
#include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtpbaseelements.h"
#include "jkqtcommon/jkqtpenhancedpainter.h" #include "jkqtcommon/jkqtpenhancedpainter.h"
#include "jkqtcommon/jkqtpconcurrencytools.h"
#include "jkqtplotter/gui/jkqtpenhancedspinboxes.h" #include "jkqtplotter/gui/jkqtpenhancedspinboxes.h"
#include <QObject> #include <QObject>
@ -2032,8 +2033,6 @@ class JKQTPLOTTER_LIB_EXPORT JKQTBasePlotter: public QObject {
*/ */
void enableDebugShowTextBoxes(bool enabled=true); void enableDebugShowTextBoxes(bool enabled=true);
protected: protected:
/** \brief this is a cache for JKQTBasePlotter::textSizeData calculated with JKQTBasePlotter::getTextSizeDetail() */
static QHash<JKQTBasePlotter::textSizeKey, JKQTBasePlotter::textSizeData> s_TextSizeDataCache;
@ -2595,6 +2594,11 @@ class JKQTPLOTTER_LIB_EXPORT JKQTBasePlotter: public QObject {
bool emitPlotSignals; bool emitPlotSignals;
static QString globalUserSettigsFilename;
static QString globalUserSettigsPrefix;
static std::mutex globalUserSettingsMutex;
static JKQTPSynchronized<QList<JKQTPPaintDeviceAdapter*>> jkqtpPaintDeviceAdapters;
static JKQTPSynchronized<QList<JKQTPSaveDataAdapter*>> jkqtpSaveDataAdapters;