From cf43dc4a7ef5822026a5de569ba627eeeb722ca1 Mon Sep 17 00:00:00 2001 From: jkriege2 Date: Sun, 25 Jun 2023 17:55:05 +0200 Subject: [PATCH] made JKQTPPlotSymbol() thread-safe --- lib/jkqtcommon/CMakeLists.txt | 3 + lib/jkqtcommon/jkqtpconcurrencytools.h | 4 - lib/jkqtcommon/jkqtpdrawingtools.cpp | 12 +- lib/jkqtcommon/jkqtpdrawingtools.h | 403 ++++++++++++------------- 4 files changed, 204 insertions(+), 218 deletions(-) diff --git a/lib/jkqtcommon/CMakeLists.txt b/lib/jkqtcommon/CMakeLists.txt index 13fd362696..296d589013 100644 --- a/lib/jkqtcommon/CMakeLists.txt +++ b/lib/jkqtcommon/CMakeLists.txt @@ -26,6 +26,7 @@ set(SOURCES ${CMAKE_CURRENT_LIST_DIR}/jkqtpstringtools.cpp ${CMAKE_CURRENT_LIST_DIR}/jkqtpcodestructuring.cpp ${CMAKE_CURRENT_LIST_DIR}/jkqtpbasicimagetools.cpp + ${CMAKE_CURRENT_LIST_DIR}/jkqtpconcurrencytools.cpp ${CMAKE_CURRENT_LIST_DIR}/jkqtpgeometrytools.cpp ${CMAKE_CURRENT_LIST_DIR}/jkqtpdrawingtools.cpp ${CMAKE_CURRENT_LIST_DIR}/jkqtpenhancedpainter.cpp @@ -59,6 +60,8 @@ set(HEADERS $ $ $ + $ + $ ) include(CMakePackageConfigHelpers) diff --git a/lib/jkqtcommon/jkqtpconcurrencytools.h b/lib/jkqtcommon/jkqtpconcurrencytools.h index c84989ef8a..a4e1e31e1c 100644 --- a/lib/jkqtcommon/jkqtpconcurrencytools.h +++ b/lib/jkqtcommon/jkqtpconcurrencytools.h @@ -59,10 +59,6 @@ public: m_data=std::move(other.m_data); } - /** \brief creates and returns a Locker-Object for this class, which is already locked */ - inline Locker get_lock() { - return Locker(*this); - } /** \brief locks the internal mutex until unlock() is called, * * \note Use Locker instances to actually lock, using a RAII-idiom, as this is safer than doing this by hand! diff --git a/lib/jkqtcommon/jkqtpdrawingtools.cpp b/lib/jkqtcommon/jkqtpdrawingtools.cpp index 7799c93e68..c85cae705c 100644 --- a/lib/jkqtcommon/jkqtpdrawingtools.cpp +++ b/lib/jkqtcommon/jkqtpdrawingtools.cpp @@ -552,16 +552,18 @@ QList JKQTPSimplifyPolyLines(const QList &lines_in, double } -QVector JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore=QVector(); +JKQTPSynchronized > JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore=QVector(); JKQTPGraphSymbols JKQTPRegisterCustomGraphSymbol(JKQTPCustomGraphSymbolFunctor&& f) { - JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore.push_back(std::move(f)); - return static_cast(static_cast(JKQTPFirstCustomSymbol)+static_cast(JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore.size()-1)); + JKQTPlotterDrawingTools::SymbolsLocker lock(JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore); + JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore->push_back(std::move(f)); + return static_cast(static_cast(JKQTPFirstCustomSymbol)+static_cast(JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore->size()-1)); } JKQTPGraphSymbols JKQTPRegisterCustomGraphSymbol(const JKQTPCustomGraphSymbolFunctor& f) { - JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore.push_back(f); - return static_cast(static_cast(JKQTPFirstCustomSymbol)+static_cast(JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore.size()-1)); + JKQTPlotterDrawingTools::SymbolsLocker lock(JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore); + JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore->push_back(f); + return static_cast(static_cast(JKQTPFirstCustomSymbol)+static_cast(JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore->size()-1)); } diff --git a/lib/jkqtcommon/jkqtpdrawingtools.h b/lib/jkqtcommon/jkqtpdrawingtools.h index 47b33c4d01..101ef5ca68 100644 --- a/lib/jkqtcommon/jkqtpdrawingtools.h +++ b/lib/jkqtcommon/jkqtpdrawingtools.h @@ -43,6 +43,7 @@ #include #include #include "jkqtcommon/jkqtpmathtools.h" +#include "jkqtcommon/jkqtpconcurrencytools.h" #include "jkqtcommon/jkqtpcodestructuring.h" class JKQTPEnhancedPainter; // forward @@ -85,7 +86,8 @@ struct JKQTPlotterDrawingTools { * \ingroup jkqtptools_drawing * \internal */ - static JKQTCOMMON_LIB_EXPORT QVector JKQTPCustomGraphSymbolStore; + static JKQTCOMMON_LIB_EXPORT JKQTPSynchronized > JKQTPCustomGraphSymbolStore; + typedef JKQTPSynchronized >::Locker SymbolsLocker; }; @@ -219,7 +221,7 @@ inline JKQTPGraphSymbols operator+(JKQTPGraphSymbols a, const QChar& b) { } -/** \brief register a JKQTPCustomGraphSymbolFunctor that draws a custom symbol.Returns an ID that allows to access the symbol! +/** \brief register a JKQTPCustomGraphSymbolFunctor that draws a custom symbol.Returns an ID that allows to access the symbol!, thread-safe * \ingroup jkqtptools_drawing * * The functor is stored in the global/static store JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore, i.e. these are available throughout the runtime of the program @@ -228,7 +230,7 @@ inline JKQTPGraphSymbols operator+(JKQTPGraphSymbols a, const QChar& b) { */ JKQTCOMMON_LIB_EXPORT JKQTPGraphSymbols JKQTPRegisterCustomGraphSymbol(JKQTPCustomGraphSymbolFunctor&&); -/** \brief register a JKQTPCustomGraphSymbolFunctor that draws a custom symbol.Returns an ID that allows to access the symbol! +/** \brief register a JKQTPCustomGraphSymbolFunctor that draws a custom symbol.Returns an ID that allows to access the symbol!, thread-safe * \ingroup jkqtptools_drawing * * The functor is stored in the global/static store JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore, i.e. these are available throughout the runtime of the program @@ -264,7 +266,7 @@ inline QDataStream& operator>>(QDataStream& str, JKQTPGraphSymbols& s) { return str; } -/*! \brief plot the specified symbol at pixel position x,y +/*! \brief plot the specified symbol at pixel position x,y, thread-safe \ingroup jkqtptools_drawing \tparam TPainter Type of \a painter: A class like JKQTPEnhancedPainter or QPainter @@ -282,7 +284,7 @@ inline QDataStream& operator>>(QDataStream& str, JKQTPGraphSymbols& s) { template inline void JKQTPPlotSymbol(TPainter& painter, double x, double y, JKQTPGraphSymbols symbol, double size, double symbolLineWidth, QColor color, QColor fillColor, QFont symbolFont); -/*! \brief plot the specified symbol at pixel position x,y +/*! \brief plot the specified symbol at pixel position x,y, thread-safe \ingroup jkqtptools_drawing \param paintDevice the paint device to draw on @@ -580,9 +582,35 @@ inline void JKQTPDrawTooltip(TPainter& painter, double x, double y, const QRectF +/*! \brief return the consecutive ccordinates of the tips of a N-tipped star on a circle of radius 1. + Inner tips are on a irle of radius \a inner_radius. + \ingroup jkqtptools_drawing + */ +template +inline std::array JKQTPGetStarCoordinates(double inner_radius=0.5) { + std::array star_coords; + const double angle=360.0/double(N)/180.0*JKQTPSTATISTICS_PI; + for (int i=0; i(i)+0.5)*angle; + star_coords[i*2]=QPointF(sin(a),cos(a)); + star_coords[i*2+1]=QPointF(inner_radius*sin(a+angle/2.0),inner_radius*cos(a+angle/2.0)); + } + return star_coords; +} - - +/** \brief internal datastructure used in JKQTPPlotSymbol() to precalculate certain data only once per runtime + * \ingroup jkqtptools_drawing + * \internal +*/ +struct JKQTPSymbolPathsInternnal { + inline JKQTPSymbolPathsInternnal(): pathsrotation(0) {}; + QPainterPath paths; + QPainterPath filledpaths; + QVector lines; + QPolygonF polygons; + QPolygonF filledpolygons; + qreal pathsrotation; +}; template @@ -601,237 +629,192 @@ inline void JKQTPPlotSymbol(TPainter& painter, double x, double y, JKQTPGraphSym const QBrush b=QBrush(fillColor, Qt::SolidPattern); - static bool pathsInitialized=false; - static std::array paths; - static std::array filledpaths; - static std::array, JKQTPSymbolCount> lines; - static std::array polygons; - static std::array filledpolygons; - static std::array pathsrotation; - if (!pathsInitialized) { + static std::vector all_paths = []() { + // this functor is called the the static variable symbolData is initialized, but only once per runtimme (guaranteed by C++) + std::vector all_paths; + all_paths.resize(JKQTPSymbolCount); + // calculate star cordinates as static values - static double s45=fabs(cos(45.0/180.0*JKQTPSTATISTICS_PI)); - static int star5_items=0; - static double star5cordsx[10]; - static double star5cordsy[10]; - if (star5_items==0) { - star5_items=5; - double angle=360.0/double(star5_items)/180.0*JKQTPSTATISTICS_PI; - for (int i=0; i(i)+0.5)*angle; - star5cordsx[i*2]=sin(a); - star5cordsx[i*2+1]=0.5*sin(a+angle/2.0); - star5cordsy[i*2]=cos(a); - star5cordsy[i*2+1]=0.5*cos(a+angle/2.0); - } - } - static int star6_items=0; - static double star6cordsx[12]; - static double star6cordsy[12]; - if (star6_items==0) { - star6_items=6; - double angle=360.0/double(star6_items)/180.0*JKQTPSTATISTICS_PI; - for (int i=0; i(i)+0.5)*angle; - star6cordsx[i*2]=sin(a); - star6cordsx[i*2+1]=0.5*sin(a+angle/2.0); - star6cordsy[i*2]=cos(a); - star6cordsy[i*2+1]=0.5*cos(a+angle/2.0); - } - } - static int star8_items=0; - static double star8cordsx[16]; - static double star8cordsy[16]; - if (star8_items==0) { - star8_items=8; - double angle=360.0/double(star8_items)/180.0*JKQTPSTATISTICS_PI; - for (int i=0; i(i)+0.5)*angle; - star8cordsx[i*2]=sin(a); - star8cordsx[i*2+1]=0.5*sin(a+angle/2.0); - star8cordsy[i*2]=cos(a); - star8cordsy[i*2+1]=0.5*cos(a+angle/2.0); - } - } + const double s45=fabs(cos(45.0/180.0*JKQTPSTATISTICS_PI)); + const auto star5cords=JKQTPGetStarCoordinates<5>(0.5); + const auto star6cords=JKQTPGetStarCoordinates<6>(0.5); + const auto star8cords=JKQTPGetStarCoordinates<8>(0.5); - pathsrotation.fill(0); - paths[JKQTPCross].moveTo(-0.5,-0.5); - paths[JKQTPCross].lineTo(0.5,0.5); - paths[JKQTPCross].moveTo(-0.5,+0.5); - paths[JKQTPCross].lineTo(+0.5,-0.5); - paths[JKQTPPlus].moveTo(-0.5,0); - paths[JKQTPPlus].lineTo(0.5,0); - paths[JKQTPPlus].moveTo(0,+0.5); - paths[JKQTPPlus].lineTo(0,-0.5); - paths[JKQTPCircle].addEllipse(QPointF(0,0), 0.5, 0.5); - filledpaths[JKQTPFilledCircle]=paths[JKQTPCircle]; - paths[JKQTPCircleCross].addEllipse(QPointF(0,0), 0.5, 0.5); - paths[JKQTPCircleCross].moveTo(-0.5*s45,-0.5*s45); - paths[JKQTPCircleCross].lineTo(0.5*s45,0.5*s45); - paths[JKQTPCircleCross].moveTo(-0.5*s45,+0.5*s45); - paths[JKQTPCircleCross].lineTo(+0.5*s45,-0.5*s45); - paths[JKQTPCirclePlus].addEllipse(QPointF(0,0), 0.5, 0.5); - paths[JKQTPCirclePlus].moveTo(-0.5,0); - paths[JKQTPCirclePlus].lineTo(0.5,0); - paths[JKQTPCirclePlus].moveTo(0,+0.5); - paths[JKQTPCirclePlus].lineTo(0,-0.5); - paths[JKQTPCirclePeace].addEllipse(QPointF(0,0), 0.5, 0.5); - paths[JKQTPCirclePeace].moveTo(0,-0.5); - paths[JKQTPCirclePeace].lineTo(0, 0.5); - paths[JKQTPCirclePeace].moveTo(0,0); - paths[JKQTPCirclePeace].lineTo(0.5*s45,0.5*s45); - paths[JKQTPCirclePeace].moveTo(0,0); - paths[JKQTPCirclePeace].lineTo(-0.5*s45,0.5*s45); - paths[JKQTPPeace].moveTo(0,-0.5); - paths[JKQTPPeace].lineTo(0, 0.5); - paths[JKQTPPeace].moveTo(0,0); - paths[JKQTPPeace].lineTo(0.5*s45,0.5*s45); - paths[JKQTPPeace].moveTo(0,0); - paths[JKQTPPeace].lineTo(-0.5*s45,0.5*s45); - paths[JKQTPTarget].addEllipse(QPointF(0,0), 0.33333, 0.33333); - paths[JKQTPTarget].moveTo(QPointF(0,-0.5)); - paths[JKQTPTarget].lineTo(QPointF(0,0.5)); - paths[JKQTPTarget].moveTo(QPointF(-0.5,0)); - paths[JKQTPTarget].lineTo(QPointF(0.5,0)); - paths[JKQTPFemale].addEllipse(-0.25,-0.5,0.5,0.5); - paths[JKQTPFemale].moveTo(0,0); - paths[JKQTPFemale].lineTo(0,0.5); - paths[JKQTPFemale].moveTo(-0.5/3.0,0.5/2.0); - paths[JKQTPFemale].lineTo(0.5/3.0,0.5/2.0); - paths[JKQTPMale].addEllipse(QRectF(-0.5/2.0, -0.5/2.0, 0.5, 0.5)); - paths[JKQTPMale].moveTo(QPointF(+0.5/2.0*cos(45.0/180.0*JKQTPSTATISTICS_PI),-0.5/2.0*cos(45.0/180.0*JKQTPSTATISTICS_PI))); - paths[JKQTPMale].lineTo(QPointF(+0.5,-0.5)); - paths[JKQTPMale].moveTo(QPointF(+0.5-0.5/2.0,-0.5)); - paths[JKQTPMale].lineTo(QPointF(+0.5,-0.5)); - paths[JKQTPMale].lineTo(QPointF(+0.5,-0.5+0.5/2.0)); - paths[JKQTPRect].addRect(-0.5,-0.5, 1,1); - filledpaths[JKQTPFilledRect]=paths[JKQTPRect]; - paths[JKQTPRectCross].addRect(-0.5,-0.5, 1,1); - paths[JKQTPRectCross].moveTo(-0.5,-0.5); - paths[JKQTPRectCross].lineTo(0.5,0.5); - paths[JKQTPRectCross].moveTo(-0.5,+0.5); - paths[JKQTPRectCross].lineTo(+0.5,-0.5); - paths[JKQTPRectPlus].addRect(-0.5,-0.5, 1,1); - paths[JKQTPRectPlus].moveTo(-0.5,0); - paths[JKQTPRectPlus].lineTo(0.5,0); - paths[JKQTPRectPlus].moveTo(0,+0.5); - paths[JKQTPRectPlus].lineTo(0,-0.5); - paths[JKQTPCurvedTriangle].moveTo(0,0-0.5); - paths[JKQTPCurvedTriangle].quadTo(0-1.0/10.0,0+1.0/4.0, 0-0.5,0+0.5); - paths[JKQTPCurvedTriangle].quadTo(0,0+1.0/4.0, 0+0.5,0+0.5); - paths[JKQTPCurvedTriangle].quadTo(0+1.0/10.0,0+1.0/4.0, 0,0-0.5); - filledpaths[JKQTPFilledCurvedTriangle]=paths[JKQTPCurvedTriangle]; + all_paths[JKQTPCross].paths.moveTo(-0.5,-0.5); + all_paths[JKQTPCross].paths.lineTo(0.5,0.5); + all_paths[JKQTPCross].paths.moveTo(-0.5,+0.5); + all_paths[JKQTPCross].paths.lineTo(+0.5,-0.5); + all_paths[JKQTPPlus].paths.moveTo(-0.5,0); + all_paths[JKQTPPlus].paths.lineTo(0.5,0); + all_paths[JKQTPPlus].paths.moveTo(0,+0.5); + all_paths[JKQTPPlus].paths.lineTo(0,-0.5); + all_paths[JKQTPCircle].paths.addEllipse(QPointF(0,0), 0.5, 0.5); + all_paths[JKQTPFilledCircle].filledpaths=all_paths[JKQTPCircle].paths; + all_paths[JKQTPCircleCross].paths.addEllipse(QPointF(0,0), 0.5, 0.5); + all_paths[JKQTPCircleCross].paths.moveTo(-0.5*s45,-0.5*s45); + all_paths[JKQTPCircleCross].paths.lineTo(0.5*s45,0.5*s45); + all_paths[JKQTPCircleCross].paths.moveTo(-0.5*s45,+0.5*s45); + all_paths[JKQTPCircleCross].paths.lineTo(+0.5*s45,-0.5*s45); + all_paths[JKQTPCirclePlus].paths.addEllipse(QPointF(0,0), 0.5, 0.5); + all_paths[JKQTPCirclePlus].paths.moveTo(-0.5,0); + all_paths[JKQTPCirclePlus].paths.lineTo(0.5,0); + all_paths[JKQTPCirclePlus].paths.moveTo(0,+0.5); + all_paths[JKQTPCirclePlus].paths.lineTo(0,-0.5); + all_paths[JKQTPCirclePeace].paths.addEllipse(QPointF(0,0), 0.5, 0.5); + all_paths[JKQTPCirclePeace].paths.moveTo(0,-0.5); + all_paths[JKQTPCirclePeace].paths.lineTo(0, 0.5); + all_paths[JKQTPCirclePeace].paths.moveTo(0,0); + all_paths[JKQTPCirclePeace].paths.lineTo(0.5*s45,0.5*s45); + all_paths[JKQTPCirclePeace].paths.moveTo(0,0); + all_paths[JKQTPCirclePeace].paths.lineTo(-0.5*s45,0.5*s45); + all_paths[JKQTPPeace].paths.moveTo(0,-0.5); + all_paths[JKQTPPeace].paths.lineTo(0, 0.5); + all_paths[JKQTPPeace].paths.moveTo(0,0); + all_paths[JKQTPPeace].paths.lineTo(0.5*s45,0.5*s45); + all_paths[JKQTPPeace].paths.moveTo(0,0); + all_paths[JKQTPPeace].paths.lineTo(-0.5*s45,0.5*s45); + all_paths[JKQTPTarget].paths.addEllipse(QPointF(0,0), 0.33333, 0.33333); + all_paths[JKQTPTarget].paths.moveTo(QPointF(0,-0.5)); + all_paths[JKQTPTarget].paths.lineTo(QPointF(0,0.5)); + all_paths[JKQTPTarget].paths.moveTo(QPointF(-0.5,0)); + all_paths[JKQTPTarget].paths.lineTo(QPointF(0.5,0)); + all_paths[JKQTPFemale].paths.addEllipse(-0.25,-0.5,0.5,0.5); + all_paths[JKQTPFemale].paths.moveTo(0,0); + all_paths[JKQTPFemale].paths.lineTo(0,0.5); + all_paths[JKQTPFemale].paths.moveTo(-0.5/3.0,0.5/2.0); + all_paths[JKQTPFemale].paths.lineTo(0.5/3.0,0.5/2.0); + all_paths[JKQTPMale].paths.addEllipse(QRectF(-0.5/2.0, -0.5/2.0, 0.5, 0.5)); + all_paths[JKQTPMale].paths.moveTo(QPointF(+0.5/2.0*cos(45.0/180.0*JKQTPSTATISTICS_PI),-0.5/2.0*cos(45.0/180.0*JKQTPSTATISTICS_PI))); + all_paths[JKQTPMale].paths.lineTo(QPointF(+0.5,-0.5)); + all_paths[JKQTPMale].paths.moveTo(QPointF(+0.5-0.5/2.0,-0.5)); + all_paths[JKQTPMale].paths.lineTo(QPointF(+0.5,-0.5)); + all_paths[JKQTPMale].paths.lineTo(QPointF(+0.5,-0.5+0.5/2.0)); + all_paths[JKQTPRect].paths.addRect(-0.5,-0.5, 1,1); + all_paths[JKQTPFilledRect].filledpaths=all_paths[JKQTPRect].paths; + all_paths[JKQTPRectCross].paths.addRect(-0.5,-0.5, 1,1); + all_paths[JKQTPRectCross].paths.moveTo(-0.5,-0.5); + all_paths[JKQTPRectCross].paths.lineTo(0.5,0.5); + all_paths[JKQTPRectCross].paths.moveTo(-0.5,+0.5); + all_paths[JKQTPRectCross].paths.lineTo(+0.5,-0.5); + all_paths[JKQTPRectPlus].paths.addRect(-0.5,-0.5, 1,1); + all_paths[JKQTPRectPlus].paths.moveTo(-0.5,0); + all_paths[JKQTPRectPlus].paths.lineTo(0.5,0); + all_paths[JKQTPRectPlus].paths.moveTo(0,+0.5); + all_paths[JKQTPRectPlus].paths.lineTo(0,-0.5); + all_paths[JKQTPCurvedTriangle].paths.moveTo(0,0-0.5); + all_paths[JKQTPCurvedTriangle].paths.quadTo(0-1.0/10.0,0+1.0/4.0, 0-0.5,0+0.5); + all_paths[JKQTPCurvedTriangle].paths.quadTo(0,0+1.0/4.0, 0+0.5,0+0.5); + all_paths[JKQTPCurvedTriangle].paths.quadTo(0+1.0/10.0,0+1.0/4.0, 0,0-0.5); + all_paths[JKQTPFilledCurvedTriangle].filledpaths=all_paths[JKQTPCurvedTriangle].paths; - paths[JKQTPDownCurvedTriangle]=paths[JKQTPCurvedTriangle]; - pathsrotation[JKQTPDownCurvedTriangle]=180.0; - filledpaths[JKQTPFilledDownCurvedTriangle]=paths[JKQTPDownCurvedTriangle]; - pathsrotation[JKQTPFilledDownCurvedTriangle]=180.0; + all_paths[JKQTPDownCurvedTriangle].paths=all_paths[JKQTPCurvedTriangle].paths; + all_paths[JKQTPDownCurvedTriangle].pathsrotation=180.0; + all_paths[JKQTPFilledDownCurvedTriangle].filledpaths=all_paths[JKQTPDownCurvedTriangle].paths; + all_paths[JKQTPFilledDownCurvedTriangle].pathsrotation=180.0; - paths[JKQTPLeftCurvedTriangle]=paths[JKQTPCurvedTriangle]; - pathsrotation[JKQTPLeftCurvedTriangle]=-90.0; - filledpaths[JKQTPFilledLeftCurvedTriangle]=paths[JKQTPLeftCurvedTriangle]; - pathsrotation[JKQTPFilledLeftCurvedTriangle]=-90.0; + all_paths[JKQTPLeftCurvedTriangle].paths=all_paths[JKQTPCurvedTriangle].paths; + all_paths[JKQTPLeftCurvedTriangle].pathsrotation=-90.0; + all_paths[JKQTPFilledLeftCurvedTriangle].filledpaths=all_paths[JKQTPLeftCurvedTriangle].paths; + all_paths[JKQTPFilledLeftCurvedTriangle].pathsrotation=-90.0; - paths[JKQTPRightCurvedTriangle]=paths[JKQTPCurvedTriangle]; - pathsrotation[JKQTPRightCurvedTriangle]=90.0; - filledpaths[JKQTPFilledRightCurvedTriangle]=paths[JKQTPRightCurvedTriangle]; - pathsrotation[JKQTPFilledRightCurvedTriangle]=90.0; + all_paths[JKQTPRightCurvedTriangle].paths=all_paths[JKQTPCurvedTriangle].paths; + all_paths[JKQTPRightCurvedTriangle].pathsrotation=90.0; + all_paths[JKQTPFilledRightCurvedTriangle].filledpaths=all_paths[JKQTPRightCurvedTriangle].paths; + all_paths[JKQTPFilledRightCurvedTriangle].pathsrotation=90.0; { QPolygonF poly; - painter.setBrush(QColor(Qt::transparent)); poly<=JKQTPFirstCustomSymbol) { + JKQTPlotterDrawingTools::SymbolsLocker lock(JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore); const int idx(static_cast(symbol-JKQTPFirstCustomSymbol)); - if (idx>=0 && idx=0 && idxsize()) { painter.setPen(p); painter.translate(QPointF(x,y)); painter.scale(symbolSize,symbolSize); painter.setBrush(b); painter.setPen(pDescaled); - JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore[idx].operator()(painter); + const auto functor=JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore->at(idx); + functor(painter); } } }