diff --git a/doc/dox/whatsnew.dox b/doc/dox/whatsnew.dox
index f5738ea573..5d338ce692 100644
--- a/doc/dox/whatsnew.dox
+++ b/doc/dox/whatsnew.dox
@@ -44,6 +44,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
NEW: made it's delay a global static variable that can be set and red with JKQTPlotter::setGlobalResizeDelay() and JKQTPlotter::getGlobalResizeDelay()
NEW: Using JKQTMathText::useGuiFonts() for FONT rendering by default
NEW: added the option to draw a character from a font as symbol (JKQTPCharacterSymbol+QChar('C').unicode()
and JKQTPFilledCharacterSymbol+QChar('C').unicode()
)
+ NEW: added the option to register a custom symbol using JKQTPRegisterCustomGraphSymbol()
JKQTMathText:
diff --git a/doc/images/symbols/symbol_custom.png b/doc/images/symbols/symbol_custom.png
new file mode 100644
index 0000000000..c573146340
Binary files /dev/null and b/doc/images/symbols/symbol_custom.png differ
diff --git a/lib/jkqtcommon/jkqtpdrawingtools.cpp b/lib/jkqtcommon/jkqtpdrawingtools.cpp
index 6d9b6178d9..eb92f0a3c9 100644
--- a/lib/jkqtcommon/jkqtpdrawingtools.cpp
+++ b/lib/jkqtcommon/jkqtpdrawingtools.cpp
@@ -93,6 +93,7 @@ QString JKQTPGraphSymbols2String(JKQTPGraphSymbols pos) {
case JKQTPSymbolCount: JKQTPGraphSymbols2String(JKQTPMaxSymbolID);
case JKQTPCharacterSymbol:
case JKQTPFilledCharacterSymbol:
+ case JKQTPFirstCustomSymbol:
break;
}
if (pos>=JKQTPCharacterSymbol && pos<=JKQTPCharacterSymbol+0xFFFF) {
@@ -105,6 +106,10 @@ QString JKQTPGraphSymbols2String(JKQTPGraphSymbols pos) {
while (s.size()<4) s="0"+s;
return "symbol_filled_char"+s;
}
+ if (pos>=JKQTPFirstCustomSymbol) {
+ QString s=QString::number(pos-JKQTPFirstCustomSymbol);
+ return "symbol_custom"+s;
+ }
return "";
}
@@ -177,6 +182,7 @@ QString JKQTPGraphSymbols2NameString(JKQTPGraphSymbols pos) {
case JKQTPSymbolCount: JKQTPGraphSymbols2NameString(JKQTPMaxSymbolID);
case JKQTPCharacterSymbol:
case JKQTPFilledCharacterSymbol:
+ case JKQTPFirstCustomSymbol:
break;
}
if (pos>=JKQTPCharacterSymbol && pos<=JKQTPCharacterSymbol+0xFFFF) {
@@ -185,6 +191,9 @@ QString JKQTPGraphSymbols2NameString(JKQTPGraphSymbols pos) {
if (pos>=JKQTPFilledCharacterSymbol && pos<=JKQTPFilledCharacterSymbol+0xFFFF) {
return QObject::tr("filled character")+" '"+QChar(static_cast(pos-JKQTPFilledCharacterSymbol))+"'";
}
+ if (pos>=JKQTPFirstCustomSymbol) {
+ return QObject::tr("custom symbol %1").arg(static_cast(pos-JKQTPFirstCustomSymbol));
+ }
return "";
}
JKQTPGraphSymbols String2JKQTPGraphSymbols(const QString& pos) {
@@ -279,6 +288,9 @@ JKQTPGraphSymbols String2JKQTPGraphSymbols(const QString& pos) {
if (posT.startsWith("symbol_filled_char")) {
return JKQTPFilledCharacterSymbol+posT.mid(18).toUInt(nullptr,16);
}
+ if (posT.startsWith("symbol_custom")) {
+ return JKQTPFirstCustomSymbol+posT.mid(13).toUInt();
+ }
return JKQTPNoSymbol;
}
@@ -538,3 +550,18 @@ QList JKQTPSimplifyPolyLines(const QList &lines_in, double
}
return l;
}
+
+
+QVector JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore=QVector();
+
+JKQTPGraphSymbols JKQTPRegisterCustomGraphSymbol(JKQTPCustomGraphSymbolFunctor&& f)
+{
+ JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore.emplace_back(std::move(f));
+ return JKQTPFirstCustomSymbol+(JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore.size()-1);
+}
+
+JKQTPGraphSymbols JKQTPRegisterCustomGraphSymbol(const JKQTPCustomGraphSymbolFunctor& f)
+{
+ JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore.emplace_back(f);
+ return JKQTPFirstCustomSymbol+(JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore.size()-1);
+}
diff --git a/lib/jkqtcommon/jkqtpdrawingtools.h b/lib/jkqtcommon/jkqtpdrawingtools.h
index 804d6b132a..0b156ce6f8 100644
--- a/lib/jkqtcommon/jkqtpdrawingtools.h
+++ b/lib/jkqtcommon/jkqtpdrawingtools.h
@@ -38,6 +38,7 @@
#include
#include
#include
+#include
#include
#include "jkqtcommon/jkqtpmathtools.h"
#include "jkqtcommon/jkqtpcodestructuring.h"
@@ -46,6 +47,31 @@ class JKQTPEnhancedPainter; // forward
+/** \brief functor used to draw a custom JKQTPGraphSymbols
+ * \ingroup jkqtptools_drawing
+ *
+ * Draw the symbol with these properties:
+ * - center at (0,0)
+ * - width 1, i.e. x=-0.5...0.5
+ * - height 1, i.e. y=-0.5...0.5
+ * - you can assume that a proper pen and brush is set with the correct properties
+ * - scaling to the final size is donw by JKQTPPlotSymbol()
+ * - drawing is protected by surronding \c p.save(); and \c p.restore(); in JKQTPPlotSymbol()
+ * .
+ *
+ * As an example, the following code-snippet:
+ * \code
+ * [](QPainter& p) {
+ * p.drawEllipse(QPointF(-0.2, -0.2), 0.3, 0.3);
+ * p.setBrush(Qt::NoBrush);
+ * p.drawEllipse(QPointF(0.2, -0.2), 0.3, 0.3);
+ * p.drawEllipse(QPointF(0, 0.2), 0.3, 0.3);
+ * };
+ * \endcode
+ * generates this symbol: \image html symbols/symbol_custom.png
+ */
+typedef std::function JKQTPCustomGraphSymbolFunctor;
+
/*! \brief tool class with static values used by JKQTPlotter/JKQTBasePlotter
\ingroup jkqtptools_drawing
*/
@@ -53,6 +79,11 @@ struct JKQTPlotterDrawingTools {
/** \brief smallest linewidth any line in JKQTPlotter/JKQTBasePlotter may have
*/
static JKQTCOMMON_LIB_EXPORT const double ABS_MIN_LINEWIDTH;
+ /** \brief stores all custom JKQTPGraphSymbols registered using JKQTPRegisterCustomGraphSymbol
+ * \ingroup jkqtptools_drawing
+ * \internal
+ */
+ static JKQTCOMMON_LIB_EXPORT QVector JKQTPCustomGraphSymbolStore;
};
@@ -142,9 +173,11 @@ enum JKQTPGraphSymbols: uint64_t {
\image html symbols/symbol_char_at.png "generated by JKQTPCharacterSymbol+QChar('@').unicode()"
\image html symbols/symbol_char_club.png "generated by JKQTPCharacterSymbol+QChar(0x2663).unicode()" */
JKQTPFilledCharacterSymbol=JKQTPCharacterSymbol+0xFFFF+0xF, /*!< \brief draw a font-character as symbol with defined outline-pen and fill-brush, you can use any character from a QFont by supplying \c JKQTPFilledCharacterSymbol+QChar('').unicode() as JKQTPGraphSymbols
- \image html symbols/symbol_filled_char_at.png "generated by JKQTPFilledCharacterSymbol+QChar('@').unicode()"
- \image html symbols/symbol_filled_char_club.png "generated by JKQTPFilledCharacterSymbol+QChar(0x2663).unicode()"
- */
+ \image html symbols/symbol_filled_char_at.png "generated by JKQTPFilledCharacterSymbol+QChar('@').unicode()"
+ \image html symbols/symbol_filled_char_club.png "generated by JKQTPFilledCharacterSymbol+QChar(0x2663).unicode()"
+ */
+ JKQTPFirstCustomSymbol=JKQTPFilledCharacterSymbol+0xFFFF+0xF, /*!< \brief draw a completely custom symbol, defined by supplying a functor to JKQTPRegisterCustomGraphSymbol()
+ \image html symbols/symbol_custom.png "generated by [](QPainter& p) { p.drawEllipse(QPointF(-0.2, -0.2), 0.3, 0.3); p.setBrush(Qt::NoBrush); p.drawEllipse(QPointF(0.2, -0.2), 0.3, 0.3); p.drawEllipse(QPointF(0, 0.2), 0.3, 0.3); };
" */
};
inline JKQTPGraphSymbols operator+(JKQTPGraphSymbols a, uint8_t b) {
@@ -179,6 +212,25 @@ inline JKQTPGraphSymbols operator+(JKQTPGraphSymbols a, int64_t b) {
return static_cast(static_cast(a)+b);
}
+/** \brief register a JKQTPCustomGraphSymbolFunctor that draws a custom symbol.Returns an ID that allows to access the symbol!
+ * \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
+ *
+ * \see JKQTPCustomGraphSymbolFunctor for an example
+ */
+JKQTCOMMON_LIB_EXPORT JKQTPGraphSymbols JKQTPRegisterCustomGraphSymbol(JKQTPCustomGraphSymbolFunctor&&);
+
+/** \brief register a JKQTPCustomGraphSymbolFunctor that draws a custom symbol.Returns an ID that allows to access the symbol!
+ * \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
+ *
+ * \see JKQTPCustomGraphSymbolFunctor for an example
+ */
+JKQTCOMMON_LIB_EXPORT JKQTPGraphSymbols JKQTPRegisterCustomGraphSymbol(const JKQTPCustomGraphSymbolFunctor&);
+
+
/** \brief converts a JKQTPGraphSymbols variable into a identifier string
* \ingroup jkqtptools_drawing
*/
@@ -193,6 +245,40 @@ JKQTCOMMON_LIB_EXPORT QString JKQTPGraphSymbols2NameString(JKQTPGraphSymbols pos
*/
JKQTCOMMON_LIB_EXPORT JKQTPGraphSymbols String2JKQTPGraphSymbols(const QString& pos);
+/*! \brief plot the specified symbol at pixel position x,y
+ \ingroup jkqtptools_drawing
+
+ \tparam TPainter Type of \a painter: A class like JKQTPEnhancedPainter or QPainter
+ \param painter the QPainter to draw to
+ \param x x-coordinate of the symbol center
+ \param y y-coordinate of the symbol center
+ \param symbol type of the symbol to plot, see JKQTPGraphSymbols
+ \param size size (width/height) of the symbol around (\a x , \a y)
+ \param symbolLineWidth width of the lines used to draw the symbol
+ \param color color of the symbol lines
+ \param fillColor color of the symbol filling
+ \param symbolFont font used to draw symbols like \c JKQTPCharacterSymbol+QChar('@').unicode()
+
+ */
+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
+ \ingroup jkqtptools_drawing
+
+ \param paintDevice the paint device to draw on
+ \param x x-coordinate of the symbol center
+ \param y y-coordinate of the symbol center
+ \param symbol type of the symbol to plot, see JKQTPGraphSymbols
+ \param size size (width/height) of the symbol around (\a x , \a y)
+ \param symbolLineWidth width of the lines used to draw the symbol
+ \param color color of the symbol lines
+ \param fillColor color of the symbol filling
+ \param symbolFont font used to draw symbols like \c JKQTPCharacterSymbol+QChar('@').unicode()
+
+ */
+JKQTCOMMON_LIB_EXPORT void JKQTPPlotSymbol(QPaintDevice& paintDevice, double x, double y, JKQTPGraphSymbols symbol, double size, double symbolLineWidth, QColor color, QColor fillColor, const QFont &symbolFont);
+
@@ -286,40 +372,6 @@ inline void JKQTPPlotDecoratedLine(TPainter& painter, const QLineF& l, JKQTPLine
/** \brief calculates the tail decorator size from the line width \a line_width, using decoratorSizeFactor and a non-linear scaling function that levels off towards small \a line_width and increases sub-linearly for large ones, so the arrow heads to not grow too much */
JKQTCOMMON_LIB_EXPORT double JKQTPLineDecoratorStyleCalcDecoratorSize(double line_width, double decoratorSizeFactor);
-/*! \brief plot the specified symbol at pixel position x,y
- \ingroup jkqtptools_drawing
-
- \tparam TPainter Type of \a painter: A class like JKQTPEnhancedPainter or QPainter
- \param painter the QPainter to draw to
- \param x x-coordinate of the symbol center
- \param y y-coordinate of the symbol center
- \param symbol type of the symbol to plot, see JKQTPGraphSymbols
- \param size size (width/height) of the symbol around (\a x , \a y)
- \param symbolLineWidth width of the lines used to draw the symbol
- \param color color of the symbol lines
- \param fillColor color of the symbol filling
- \param symbolFont font used to draw symbols like \c JKQTPCharacterSymbol+QChar('@').unicode()
-
- */
-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
- \ingroup jkqtptools_drawing
-
- \param paintDevice the paint device to draw on
- \param x x-coordinate of the symbol center
- \param y y-coordinate of the symbol center
- \param symbol type of the symbol to plot, see JKQTPGraphSymbols
- \param size size (width/height) of the symbol around (\a x , \a y)
- \param symbolLineWidth width of the lines used to draw the symbol
- \param color color of the symbol lines
- \param fillColor color of the symbol filling
- \param symbolFont font used to draw symbols like \c JKQTPCharacterSymbol+QChar('@').unicode()
-
- */
-JKQTCOMMON_LIB_EXPORT void JKQTPPlotSymbol(QPaintDevice& paintDevice, double x, double y, JKQTPGraphSymbols symbol, double size, double symbolLineWidth, QColor color, QColor fillColor, const QFont &symbolFont);
-
@@ -873,6 +925,7 @@ inline void JKQTPPlotSymbol(TPainter& painter, double x, double y, JKQTPGraphSym
case JKQTPSymbolCount:
case JKQTPCharacterSymbol:
case JKQTPFilledCharacterSymbol:
+ case JKQTPFirstCustomSymbol:
break;
}
if (symbol>=JKQTPCharacterSymbol && symbol<=JKQTPCharacterSymbol+0xFFFF) {
@@ -913,6 +966,17 @@ inline void JKQTPPlotSymbol(TPainter& painter, double x, double y, JKQTPGraphSym
path.addText(0,0,symbolFont, ch),
painter.drawPath(path);
}
+ if (symbol>=JKQTPFirstCustomSymbol) {
+ const int idx(static_cast(symbol-JKQTPFirstCustomSymbol));
+ if (idx>=0 && idx
diff --git a/tools/jkqtplotter_doc_imagegenerator/jkqtplotter_doc_imagegenerator.cpp b/tools/jkqtplotter_doc_imagegenerator/jkqtplotter_doc_imagegenerator.cpp
index 2b93774656..6aa25ed995 100644
--- a/tools/jkqtplotter_doc_imagegenerator/jkqtplotter_doc_imagegenerator.cpp
+++ b/tools/jkqtplotter_doc_imagegenerator/jkqtplotter_doc_imagegenerator.cpp
@@ -105,6 +105,18 @@ int main(int argc, char* argv[])
p.setPen(QPen(QColor("green"),0.5));
//p.drawRect(2,2,iconsize-4,iconsize-4);
stopPaintingAndSave(img, p, outputDir.absoluteFilePath("symbol_filled_char_club.png"));
+
+ JKQTPCustomGraphSymbolFunctor f=[](QPainter& p) {
+ p.drawEllipse(QPointF(-0.2, -0.2), 0.3, 0.3);
+ p.setBrush(Qt::NoBrush);
+ p.drawEllipse(QPointF(0.2, -0.2), 0.3, 0.3);
+ p.drawEllipse(QPointF(0, 0.2), 0.3, 0.3);
+ };
+ JKQTPGraphSymbols customs=JKQTPRegisterCustomGraphSymbol(f);
+ startPainting(img, p, iconsize, backgroundColor);
+ JKQTPPlotSymbol(p, iconsize/2,iconsize/2,customs,iconsize-4,2,QColor("blue"), QColor("salmon").lighter(120),QGuiApplication::font().family());
+ p.setPen(QPen(QColor("green"),0.5));
+ stopPaintingAndSave(img, p, outputDir.absoluteFilePath("symbol_custom.png"));
}
if (listlinedecorators) {