mirror of
https://github.com/jkriege2/JKQtPlotter.git
synced 2024-12-25 01:51:49 +08:00
NEW/REWORKED: extended the set of functions like JKQTMathTextGetTightBoundingRect(): These use an internal, thread-safe cache and capsule calls to QFontMetricsF-instances. This significantly improves speed in (parallelized) plotting.
This commit is contained in:
parent
3fee9609fb
commit
09e07cb12a
@ -97,10 +97,10 @@ This test results in the following numbers (on my AMD Ryzen5 8/16-core laptop):
|
||||
<b>VERSION:</b> 5.0.0
|
||||
<b>BUILD MODE:</b> Release
|
||||
|
||||
<u><b>SERIAL RESULTS:</b></u><br/>runtime, overall = 1896.0ms<br/>single runtimes = (236.9 +/- 379.1) ms<br/>speedup = 1.00x<br/>threads / available = 1 / 16<br/><br/>
|
||||
<u><b>SERIAL RESULTS:</b></u><br/>runtime, overall = 3399.6ms<br/>single runtimes = (141.6 +/- 366.9) ms<br/>speedup = 1.00x<br/>threads / available = 1 / 16<br/><br/><br/>
|
||||
|
||||
<u><b>PARALLEL RESULTS:</b></u><br/>
|
||||
runtime, overall = 624.7ms<br/>single runtimes = (564.3 +/- 107.7) ms<br/>speedup = 7.23x<br/>threads / available = 8 / 16<br/><br/><b>speedup vs. serial = 3.0x</b>
|
||||
runtime, overall = 526.7ms<br/>single runtimes = (166.4 +/- 9.9) ms<br/>speedup = 7.58x<br/>threads / available = 8 / 16<br/>batch runs = 3<br/><br/><b>speedup vs. serial = 6.5x</b>
|
||||
|
||||
[comment]:RESULTS_END
|
||||
|
||||
@ -108,8 +108,9 @@ runtime, overall = 624.7ms<br/>single runtimes = (564.3 +/- 107.7) ms<br/>speedu
|
||||
|
||||
From this data you can observe:
|
||||
- The plotting parallelizes nicely, i.e. the speedup ist >7x on a 8-core-machine. This is the speedup calculated as sum of runtimes of each thread, divided by the runtime of all threads in parallel.
|
||||
- BUT: the speedup of serialized plotting vs. parallel plotting is way smaller: It is only 2-3x. Also the runtime in each thread is about 3x longer than in the serialized example. This can be explained by the (significant) overhead due to shared caches (and therefore synchronization) between the plotters. This may be reworked in future!
|
||||
- BUT: the speedup of serialized plotting vs. parallel plotting is a biz smaller: It is only 6-7x. Also the runtime in each thread is a bit longer than in the serialized example. This can be explained by the overhead due to shared caches (and therefore synchronization) between the plotters (e.g. using JKQTMathTextGetBoundingRect() within JKQTMathText).
|
||||
- The variance in runtimes in the (initial) serial test-run is larger than in the parallel run. This is due to filling of the internal caches during the first plotting!
|
||||
- NOTE: The parallel vs. serial speedup significantly depends on the complexity of the text rendering (i.e. usage of JKQTMathText). Therefore rendinering more complex textxs with more and more complex LaTeX markup, will result in smalle speedups!
|
||||
.
|
||||
|
||||
Finally the application displays the plots:
|
||||
|
@ -21,6 +21,7 @@
|
||||
#define NUM_PLOTS 8
|
||||
#define NUM_GRAPHS 6
|
||||
#define NUM_DATAPOINTS 1000
|
||||
#define NUM_REPEATS 3
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
@ -33,11 +34,21 @@ int main(int argc, char* argv[])
|
||||
mainWin->setCentralWidget(main=new QWidget(mainWin));
|
||||
|
||||
QString markdownFile="";
|
||||
QString labelTemplate="Plot %1: $f(x)=\\cos\\left(x+\\sfrac{%1\\pi}{8}\\right)$";
|
||||
QByteArray mdMATCH="RESULTS";
|
||||
for (int i=1; i<argc; i++) {
|
||||
if (QString(argv[i]).startsWith("--mdfile=")) {
|
||||
markdownFile=QString::fromLatin1(argv[i]).right(QString::fromLatin1(argv[i]).size()-9);
|
||||
if (markdownFile.startsWith('"')) markdownFile.remove('"');
|
||||
}
|
||||
if (QString(argv[i]).startsWith("--complexlabel")) {
|
||||
labelTemplate="Plot %1: $f(x)=\\cos\\left(x+\\sfrac{%1\\pi}{8}\\right)$";
|
||||
mdMATCH="COMPLEXRESULTS";
|
||||
}
|
||||
if (QString(argv[i]).startsWith("--simplelabel")) {
|
||||
labelTemplate="Plot %1: $f(x)=\\cos(x+%1\\pi/8)$";
|
||||
mdMATCH="COMPLEXRESULTS";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -72,40 +83,45 @@ int main(int argc, char* argv[])
|
||||
lay_serial->addWidget(pic_serial.last(), 1);
|
||||
lay_parallel->addWidget(pic_parallel.last(), 1);
|
||||
}
|
||||
|
||||
QElapsedTimer timer;
|
||||
QList<double> runtimesSerial;
|
||||
timer.start();
|
||||
for (int i=0; i<NUM_PLOTS; i++) {
|
||||
double dur=0;
|
||||
filenamesSerial<<PlottingThread::plotAndSave("serial", i, NUM_GRAPHS, NUM_DATAPOINTS, &dur);
|
||||
runtimesSerial<<dur/1e6;
|
||||
}
|
||||
const double durSerialNano=timer.nsecsElapsed();
|
||||
qDebug()<<"durSerial = "<<durSerialNano/1e6<<"ms";
|
||||
|
||||
QList<double> runtimesParallel;
|
||||
QList<QSharedPointer<PlottingThread>> threads;
|
||||
for (int i=0; i<NUM_PLOTS; i++) {
|
||||
qDebug()<<" creating thread "<<i;
|
||||
threads.append(QSharedPointer<PlottingThread>::create("parallel",i, NUM_GRAPHS, NUM_DATAPOINTS, nullptr));
|
||||
}
|
||||
timer.start();
|
||||
for (int i=0; i<NUM_PLOTS; i++) {
|
||||
qDebug()<<" staring thread "<<i;
|
||||
threads[i]->start();
|
||||
}
|
||||
for (int i=0; i<NUM_PLOTS; i++) {
|
||||
qDebug()<<" waiting for thread "<<i;
|
||||
if (threads[i]->wait()) {
|
||||
filenamesParallel<<threads[i]->getFilename();
|
||||
runtimesParallel<<threads[i]->getRuntimeNanosends()/1e6;
|
||||
}
|
||||
}
|
||||
const double durParallelNano=timer.nsecsElapsed();
|
||||
qDebug()<<"durParallel = "<<durParallelNano/1e6<<"ms";
|
||||
QList<double> runtimesSerial;
|
||||
double durSerialNano=0;
|
||||
double durParallelNano=0;
|
||||
for (int run=0; run<NUM_REPEATS; run++) {
|
||||
filenamesParallel.clear();
|
||||
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
for (int i=0; i<NUM_PLOTS; i++) {
|
||||
double dur=0;
|
||||
filenamesSerial<<PlottingThread::plotAndSave("serial", i, NUM_GRAPHS, NUM_DATAPOINTS, labelTemplate, &dur);
|
||||
runtimesSerial<<dur/1e6;
|
||||
}
|
||||
durSerialNano+=timer.nsecsElapsed();
|
||||
qDebug()<<"durSerial = "<<durSerialNano/1e6<<"ms";
|
||||
|
||||
QList<QSharedPointer<PlottingThread>> threads;
|
||||
for (int i=0; i<NUM_PLOTS; i++) {
|
||||
qDebug()<<" creating thread "<<i;
|
||||
threads.append(QSharedPointer<PlottingThread>::create("parallel",i, NUM_GRAPHS, NUM_DATAPOINTS, labelTemplate, nullptr));
|
||||
}
|
||||
timer.start();
|
||||
for (int i=0; i<NUM_PLOTS; i++) {
|
||||
qDebug()<<" staring thread "<<i;
|
||||
threads[i]->start();
|
||||
}
|
||||
for (int i=0; i<NUM_PLOTS; i++) {
|
||||
qDebug()<<" waiting for thread "<<i;
|
||||
if (threads[i]->wait()) {
|
||||
filenamesParallel<<threads[i]->getFilename();
|
||||
runtimesParallel<<threads[i]->getRuntimeNanosends()/1e6;
|
||||
}
|
||||
}
|
||||
durParallelNano+=timer.nsecsElapsed();
|
||||
qDebug()<<"durParallel["<<run+1<<"] = "<<durParallelNano/1e6<<"ms";
|
||||
threads.clear();
|
||||
}
|
||||
|
||||
threads.clear();
|
||||
|
||||
for (int ii=0; ii<NUM_SHOWN_PLOTS; ii++) {
|
||||
int i=ii;
|
||||
@ -114,8 +130,8 @@ int main(int argc, char* argv[])
|
||||
pic_parallel[ii]->setPixmap(QPixmap(filenamesParallel[i], "PNG"));
|
||||
}
|
||||
QString ser_result, par_result;
|
||||
labSerialResult->setText(ser_result=QString("runtime, overall = %1ms<br/>single runtimes = (%2 +/- %3) ms<br/>speedup = %4x<br/>threads / available = %5 / %6<br/><br/> ").arg(durSerialNano/1e6,0,'f',1).arg(jkqtpstatAverage(runtimesSerial.begin(), runtimesSerial.end()),0,'f',1).arg(jkqtpstatStdDev(runtimesSerial.begin(), runtimesSerial.end()),0,'f',1).arg(jkqtpstatSum(runtimesSerial.begin(), runtimesSerial.end())/(durSerialNano/1e6),0,'f',2).arg(1).arg(std::thread::hardware_concurrency()));
|
||||
labParallelResult->setText(par_result=QString("runtime, overall = %1ms<br/>single runtimes = (%2 +/- %3) ms<br/>speedup = %4x<br/>threads / available = %5 / %6<br/><br/><b>speedup vs. serial = %7x</b>").arg(durParallelNano/1e6,0,'f',1).arg(jkqtpstatAverage(runtimesParallel.begin(), runtimesParallel.end()),0,'f',1).arg(jkqtpstatStdDev(runtimesParallel.begin(), runtimesParallel.end()),0,'f',1).arg(jkqtpstatSum(runtimesParallel.begin(), runtimesParallel.end())/(durParallelNano/1e6),0,'f',2).arg(NUM_PLOTS).arg(std::thread::hardware_concurrency()).arg(durSerialNano/durParallelNano,0,'f',1));
|
||||
labSerialResult->setText(ser_result=QString("runtime, overall = %1ms<br/>single runtimes = (%2 +/- %3) ms<br/>speedup = %4x<br/>threads / available = %5 / %6<br/><br/><br/> ").arg(durSerialNano/1e6,0,'f',1).arg(jkqtpstatAverage(runtimesSerial.begin(), runtimesSerial.end()),0,'f',1).arg(jkqtpstatStdDev(runtimesSerial.begin(), runtimesSerial.end()),0,'f',1).arg(jkqtpstatSum(runtimesSerial.begin(), runtimesSerial.end())/(durSerialNano/1e6),0,'f',2).arg(1).arg(std::thread::hardware_concurrency()));
|
||||
labParallelResult->setText(par_result=QString("runtime, overall = %1ms<br/>single runtimes = (%2 +/- %3) ms<br/>speedup = %4x<br/>threads / available = %5 / %6<br/>batch runs = %8<br/><br/><b>speedup vs. serial = %7x</b>").arg(durParallelNano/1e6,0,'f',1).arg(jkqtpstatAverage(runtimesParallel.begin(), runtimesParallel.end()),0,'f',1).arg(jkqtpstatStdDev(runtimesParallel.begin(), runtimesParallel.end()),0,'f',1).arg(jkqtpstatSum(runtimesParallel.begin(), runtimesParallel.end())/(durParallelNano/1e6),0,'f',2).arg(NUM_PLOTS).arg(std::thread::hardware_concurrency()).arg(durSerialNano/durParallelNano,0,'f',1).arg(NUM_REPEATS));
|
||||
mainWin->show();
|
||||
|
||||
if (!markdownFile.isEmpty()) {
|
||||
@ -126,11 +142,11 @@ int main(int argc, char* argv[])
|
||||
md=f.readAll();
|
||||
qDebug()<<" read "<<md.size()<<" bytes";
|
||||
f.close();
|
||||
const auto istart=md.indexOf("[comment]:RESULTS");
|
||||
const auto iend=md.indexOf("[comment]:RESULTS_END");
|
||||
const auto istart=md.indexOf("[comment]:"+mdMATCH);
|
||||
const auto iend=md.indexOf("[comment]:"+mdMATCH+"_END");
|
||||
qDebug()<<" istart="<<istart<<", iend="<<iend;
|
||||
if (istart>=0 && iend>istart) {
|
||||
const QByteArray newResults="[comment]:RESULTS\n\n<b>VERSION:</b> "+QByteArray(JKQTPLOTTER_VERSION::PROJECT_VERSION)
|
||||
const QByteArray newResults="[comment]:"+mdMATCH+"\n\n<b>VERSION:</b> "+QByteArray(JKQTPLOTTER_VERSION::PROJECT_VERSION)
|
||||
+"\n<b>BUILD MODE:</b> "+QByteArray(JKQTPLOTTER_VERSION::PROJECT_BUILDTYPE)
|
||||
+"\n\n<u><b>SERIAL RESULTS:</b></u><br/>"+ser_result.toUtf8()
|
||||
+"\n\n<u><b>PARALLEL RESULTS:</b></u><br/>\n"+par_result.toUtf8()+"\n\n";
|
||||
|
@ -14,17 +14,18 @@
|
||||
class PlottingThread: public QThread {
|
||||
Q_OBJECT
|
||||
public:
|
||||
inline PlottingThread(const QString& filenamepart, int plotindex, int NUM_GRAPHS, int NUM_DATAPOINTS, QObject* parent):
|
||||
inline PlottingThread(const QString& filenamepart, int plotindex, int NUM_GRAPHS, int NUM_DATAPOINTS, const QString& labeltemplate, QObject* parent):
|
||||
QThread(parent),
|
||||
m_plotindex(plotindex),
|
||||
m_runtimeNanoseconds(0),
|
||||
m_filenamepart(filenamepart),
|
||||
m_filename(),
|
||||
m_NUM_GRAPHS(NUM_GRAPHS),
|
||||
m_NUM_DATAPOINTS(NUM_DATAPOINTS)
|
||||
m_NUM_DATAPOINTS(NUM_DATAPOINTS),
|
||||
m_labeltemplate(labeltemplate)
|
||||
{}
|
||||
|
||||
inline static QString plotAndSave(const QString& filenamepart, int plotIndex, int NUM_GRAPHS, int NUM_DATAPOINTS, double* runtimeNanoseconds=nullptr) {
|
||||
inline static QString plotAndSave(const QString& filenamepart, int plotIndex, int NUM_GRAPHS, int NUM_DATAPOINTS, const QString& labeltemplate, double* runtimeNanoseconds=nullptr) {
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
const QString filename=QDir(QDir::tempPath()).absoluteFilePath(QString("testimg_%1_%2.png").arg(filenamepart).arg(plotIndex));
|
||||
@ -36,15 +37,15 @@ public:
|
||||
JKQTPXYLineGraph* g;
|
||||
plot.addGraph(g=new JKQTPXYLineGraph(&plot));
|
||||
g->setXColumn(colX);
|
||||
g->setYColumn(plot.getDatastore()->addColumnCalculatedFromColumn(colX, [&](double x) { return cos(x+double(i)/8.0*JKQTPSTATISTICS_PI)+rng.generateDouble()*0.2-0.1;}));
|
||||
g->setTitle(QString("Plot %1: $f(x)=\\cos\\leftx+\\frac{%1\\pi}{8}\\right)").arg(i+1));
|
||||
g->setYColumn(plot.getDatastore()->addColumnCalculatedFromColumn(colX, [&](double x) { return cos(x+double(i+plotIndex)/8.0*JKQTPSTATISTICS_PI)+rng.generateDouble()*0.2-0.1;}));
|
||||
g->setTitle(labeltemplate.arg(i+plotIndex+1));
|
||||
g->setDrawLine(true);
|
||||
g->setSymbolType(JKQTPNoSymbol);
|
||||
|
||||
}
|
||||
plot.setPlotLabel(QString("Test Plot %1").arg(plotIndex+1));
|
||||
plot.getXAxis()->setAxisLabel("x-axis");
|
||||
plot.getYAxis()->setAxisLabel("y-axis");
|
||||
plot.setPlotLabel(QString("Test Plot %1 (%2)").arg(plotIndex+1).arg(filenamepart));
|
||||
plot.getXAxis()->setAxisLabel("x-axis $x$");
|
||||
plot.getYAxis()->setAxisLabel("y-axis $f(x)$");
|
||||
plot.zoomToFit();
|
||||
plot.saveAsPixelImage(filename, false, "PNG");
|
||||
|
||||
@ -59,15 +60,16 @@ public:
|
||||
}
|
||||
protected:
|
||||
inline virtual void run() {
|
||||
m_filename=plotAndSave(m_filenamepart, m_plotindex, m_NUM_GRAPHS, m_NUM_DATAPOINTS, &m_runtimeNanoseconds);
|
||||
m_filename=plotAndSave(m_filenamepart, m_plotindex, m_NUM_GRAPHS, m_NUM_DATAPOINTS, m_labeltemplate, &m_runtimeNanoseconds);
|
||||
}
|
||||
|
||||
int m_plotindex;
|
||||
double m_runtimeNanoseconds;
|
||||
QString m_filename;
|
||||
QString m_filenamepart;
|
||||
const QString m_filenamepart;
|
||||
const int m_NUM_GRAPHS;
|
||||
const int m_NUM_DATAPOINTS;
|
||||
const QString m_labeltemplate;
|
||||
};
|
||||
|
||||
#endif // MULTITHREADED_THREAD_H
|
||||
|
@ -71,6 +71,14 @@ class JKQTMathTextVerticalListNode; // forward
|
||||
- \ref jkqtmathtext_supportedlatex for a description of the supported LaTeX subset
|
||||
.
|
||||
|
||||
\section JKQTMathTextUsageThreadSafety Thread-Safety/Re-Entrancy Guarantees
|
||||
All functions in this class are reentrant. Therefore different instances off JKQTMathtext can be used in parallel in different threads.
|
||||
DO NOT however use the same instance from multiple threads, as the functions are not thread-safe!
|
||||
|
||||
Also note that there are certain caches that reuse information (e.g. about fonts) from previous runs, which allow different instances
|
||||
(also over different threads) to profit from each other. On the other hand, this strategy requires a bit of overhead due to synchronization,
|
||||
but usually the speedup outweighs the overhead significantly!
|
||||
|
||||
|
||||
\section JKQTMathTextUsage Usage
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "jkqtmathtext/jkqtmathtexttools.h"
|
||||
#include "jkqtmathtext/jkqtmathtext.h"
|
||||
#include "jkqtcommon/jkqtpstringtools.h"
|
||||
#include "jkqtcommon/jkqtpcachingtools.h"
|
||||
#include <cmath>
|
||||
#include <QFontMetricsF>
|
||||
#include <QDebug>
|
||||
@ -29,6 +30,7 @@
|
||||
#include <QFontInfo>
|
||||
#include <QApplication>
|
||||
#include <QFont>
|
||||
#include <QReadWriteLock>
|
||||
#include <mutex>
|
||||
|
||||
|
||||
@ -877,81 +879,239 @@ QPainterPath JKQTMathTextMakeHBracePath(double x, double ybrace, double width, d
|
||||
}
|
||||
|
||||
|
||||
JKQTMathTextTBRData::JKQTMathTextTBRData(const QFont &f, const QString &text, QPaintDevice *pd):
|
||||
fm(f, pd)
|
||||
{
|
||||
this->text=text;
|
||||
this->tbr=this->fm.tightBoundingRect(text);
|
||||
this->f=f;
|
||||
//this->pd=pd;
|
||||
if (pd) {
|
||||
ldpiX=pd->logicalDpiX();
|
||||
ldpiY=pd->logicalDpiY();
|
||||
pdpiX=pd->physicalDpiX();
|
||||
pdpiY=pd->physicalDpiY();
|
||||
} else {
|
||||
ldpiX=0;
|
||||
ldpiY=0;
|
||||
pdpiX=0;
|
||||
pdpiY=0;
|
||||
}
|
||||
}
|
||||
|
||||
bool JKQTMathTextTBRData::operator==(const JKQTMathTextTBRData &other) const
|
||||
{
|
||||
return ldpiX==other.ldpiX && ldpiY==other.ldpiY && text==other.text && f==other.f;
|
||||
}
|
||||
namespace {
|
||||
|
||||
|
||||
|
||||
JKQTMathTextTBRDataH::JKQTMathTextTBRDataH(const QFont &f, const QString &text, QPaintDevice *pd)
|
||||
{
|
||||
this->text=text;
|
||||
this->f=f;
|
||||
if (pd) {
|
||||
ldpiX=pd->logicalDpiX();
|
||||
ldpiY=pd->logicalDpiY();
|
||||
pdpiX=pd->physicalDpiX();
|
||||
pdpiY=pd->physicalDpiY();
|
||||
} else {
|
||||
ldpiX=0;
|
||||
ldpiY=0;
|
||||
pdpiX=0;
|
||||
pdpiY=0;
|
||||
}
|
||||
}
|
||||
|
||||
bool JKQTMathTextTBRDataH::operator==(const JKQTMathTextTBRDataH &other) const
|
||||
{
|
||||
return ldpiX==other.ldpiX && ldpiY==other.ldpiY && text==other.text && f==other.f;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
QRectF JKQTMathTextGetTightBoundingRect(const QFont &fm, const QString &text, QPaintDevice *pd)
|
||||
{
|
||||
thread_local QList<JKQTMathTextTBRData> JKQTMathText_tbrs=QList<JKQTMathTextTBRData>();
|
||||
thread_local QHash<JKQTMathTextTBRDataH, QRectF> JKQTMathText_tbrh=QHash<JKQTMathTextTBRDataH, QRectF>();
|
||||
|
||||
JKQTMathTextTBRDataH dh(fm, text, pd);
|
||||
if (pd) {
|
||||
if (JKQTMathText_tbrh.contains(dh)) return JKQTMathText_tbrh[dh];
|
||||
/*for (int i=0; i<tbrs.size(); i++) {
|
||||
if (tbrs[i].f==fm && tbrs[i].text==text && (tbrs[i].ldpiX==pd->logicalDpiX() && tbrs[i].ldpiY==pd->logicalDpiY() && tbrs[i].pdpiX==pd->physicalDpiX() && tbrs[i].pdpiY==pd->physicalDpiY())) {
|
||||
//qDebug()<<" ### "<<fm<<pd<<tbrs[i].text<<tbrs[i].tbr;
|
||||
return tbrs[i].tbr;
|
||||
struct JKQTMathTextCacheKeyBase {
|
||||
inline explicit JKQTMathTextCacheKeyBase(const QFont& f_, QPaintDevice *pd):
|
||||
f(f_)
|
||||
{
|
||||
if (pd) {
|
||||
ldpiX=pd->logicalDpiX();
|
||||
ldpiY=pd->logicalDpiY();
|
||||
pdpiX=pd->physicalDpiX();
|
||||
pdpiY=pd->physicalDpiY();
|
||||
} else {
|
||||
ldpiX=0;
|
||||
ldpiY=0;
|
||||
pdpiX=0;
|
||||
pdpiY=0;
|
||||
}
|
||||
}*/
|
||||
} else {
|
||||
//qDebug()<<"warning no pd";
|
||||
}
|
||||
QFont f;
|
||||
int ldpiX, ldpiY, pdpiX, pdpiY;
|
||||
|
||||
inline bool operator==(const JKQTMathTextCacheKeyBase& other) const{
|
||||
return ldpiX==other.ldpiX && ldpiY==other.ldpiY && pdpiX==other.pdpiX && pdpiY==other.pdpiY && f==other.f;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
|
||||
inline size_t qHash(const JKQTMathTextCacheKeyBase& data, size_t seed=0) {
|
||||
#else
|
||||
inline uint qHash(const JKQTMathTextCacheKeyBase& data) {
|
||||
const size_t seed=0;
|
||||
#endif
|
||||
return qHash(data.f)+::qHash(data.ldpiX,seed)+::qHash(data.ldpiY)+::qHash(data.pdpiX)+::qHash(data.pdpiY);
|
||||
}
|
||||
JKQTMathTextTBRData d(fm, text, pd);
|
||||
JKQTMathText_tbrs.append(d);
|
||||
JKQTMathText_tbrh[dh]=d.tbr;
|
||||
//qDebug()<<"TBRs lits: "<<tbrs.size();
|
||||
//qDebug()<<"+++ "<<fm<<pd<<d.text<<d.tbr;
|
||||
return d.tbr;
|
||||
|
||||
struct JKQTMathTextCacheKeyBaseExt: public JKQTMathTextCacheKeyBase {
|
||||
inline explicit JKQTMathTextCacheKeyBaseExt(const QFont& f_, QPaintDevice *pd_):
|
||||
JKQTMathTextCacheKeyBase(f_,pd_), pd(pd_)
|
||||
{}
|
||||
|
||||
QPaintDevice *pd;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <class TText=QString>
|
||||
struct JKQTMathTextTBRDataH: public JKQTMathTextCacheKeyBase {
|
||||
inline explicit JKQTMathTextTBRDataH(const QFont& f_, const TText& text_, QPaintDevice *pd):
|
||||
JKQTMathTextCacheKeyBase(f_, pd), text(text_)
|
||||
{
|
||||
|
||||
}
|
||||
TText text;
|
||||
|
||||
inline bool operator==(const JKQTMathTextTBRDataH& other) const{
|
||||
return JKQTMathTextCacheKeyBase::operator==(other) && text==other.text;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template <class TText=QString>
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
|
||||
inline size_t qHash(const JKQTMathTextTBRDataH<TText>& data, size_t /*seed=0*/) {
|
||||
#else
|
||||
inline uint qHash(const JKQTMathTextTBRDataH<TText>& data) {
|
||||
#endif
|
||||
return qHash(data.f)+qHash(data.text)+::qHash(data.ldpiX)+::qHash(data.ldpiY)+::qHash(data.pdpiX)+::qHash(data.pdpiY);
|
||||
}
|
||||
|
||||
template <class TText=QString>
|
||||
struct JKQTMathTextTBRDataHExt: public JKQTMathTextTBRDataH<TText> {
|
||||
inline explicit JKQTMathTextTBRDataHExt(const QFont& f_, const TText& text_, QPaintDevice *pd_):
|
||||
JKQTMathTextTBRDataH<TText>(f_,text_,pd_), pd(pd_)
|
||||
{}
|
||||
|
||||
QPaintDevice *pd;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QRectF JKQTMathTextGetTightBoundingRect(const QFont &f, const QString &text, QPaintDevice *pd)
|
||||
{
|
||||
//thread_local JKQTPDataCache<QRectF,JKQTMathTextTBRDataH,false,JKQTMathTextTBRDataHExt> cache(
|
||||
static JKQTPDataCache<QRectF,JKQTMathTextTBRDataH<QString>,true,JKQTMathTextTBRDataHExt<QString>> cache(
|
||||
[](const JKQTMathTextTBRDataHExt<QString>& key) {
|
||||
const QFontMetricsF fm(key.f, key.pd);
|
||||
return fm.tightBoundingRect(key.text);
|
||||
});
|
||||
|
||||
return cache.get_inline(f, text, pd);
|
||||
|
||||
}
|
||||
|
||||
QRectF JKQTMathTextGetBoundingRect(const QFont &f, const QString &text, QPaintDevice *pd)
|
||||
{
|
||||
//thread_local JKQTPDataCache<QRectF,JKQTMathTextTBRDataH,false,JKQTMathTextTBRDataHExt> cache(
|
||||
static JKQTPDataCache<QRectF,JKQTMathTextTBRDataH<QString>,true,JKQTMathTextTBRDataHExt<QString>> cache(
|
||||
[](const JKQTMathTextTBRDataHExt<QString>& key) {
|
||||
const QFontMetricsF fm(key.f, key.pd);
|
||||
return fm.boundingRect(key.text);
|
||||
});
|
||||
|
||||
return cache.get_inline(f, text, pd);
|
||||
}
|
||||
|
||||
|
||||
qreal JKQTMathTextGetHorAdvance(const QFont &f, const QString &text, QPaintDevice *pd)
|
||||
{
|
||||
//thread_local JKQTPDataCache<double,JKQTMathTextTBRDataH,false,JKQTMathTextTBRDataHExt> cache(
|
||||
static JKQTPDataCache<qreal,JKQTMathTextTBRDataH<QString>,true,JKQTMathTextTBRDataHExt<QString>> cache(
|
||||
[](const JKQTMathTextTBRDataHExt<QString>& key) {
|
||||
const QFontMetricsF fm(key.f, key.pd);
|
||||
#if (QT_VERSION>=QT_VERSION_CHECK(5, 15, 0))
|
||||
return fm.horizontalAdvance(key.text);
|
||||
#else
|
||||
return fm.width(key.text);
|
||||
#endif
|
||||
});
|
||||
|
||||
return cache.get_inline(f, text, pd);
|
||||
|
||||
}
|
||||
|
||||
qreal JKQTMathTextGetRightBearing(const QFont &f, const QChar &text, QPaintDevice *pd)
|
||||
{
|
||||
//thread_local JKQTPDataCache<double,JKQTMathTextTBRDataH,false,JKQTMathTextTBRDataHExt> cache(
|
||||
static JKQTPDataCache<qreal,JKQTMathTextTBRDataH<QChar>,true,JKQTMathTextTBRDataHExt<QChar>> cache(
|
||||
[](const JKQTMathTextTBRDataHExt<QChar>& key) {
|
||||
const QFontMetricsF fm(key.f, key.pd);
|
||||
return fm.rightBearing(key.text);
|
||||
});
|
||||
|
||||
return cache.get_inline(f, text, pd);
|
||||
}
|
||||
|
||||
qreal JKQTMathTextGetLeftBearing(const QFont &f, const QChar &text, QPaintDevice *pd)
|
||||
{
|
||||
//thread_local JKQTPDataCache<double,JKQTMathTextTBRDataH,false,JKQTMathTextTBRDataHExt> cache(
|
||||
static JKQTPDataCache<qreal,JKQTMathTextTBRDataH<QChar>,true,JKQTMathTextTBRDataHExt<QChar>> cache(
|
||||
[](const JKQTMathTextTBRDataHExt<QChar>& key) {
|
||||
const QFontMetricsF fm(key.f, key.pd);
|
||||
return fm.leftBearing(key.text);
|
||||
});
|
||||
|
||||
return cache.get_inline(f, text, pd);
|
||||
|
||||
}
|
||||
|
||||
qreal JKQTMathTextGetFontAscent(const QFont &f, QPaintDevice *pd)
|
||||
{
|
||||
static JKQTPDataCache<qreal,JKQTMathTextCacheKeyBase,true,JKQTMathTextCacheKeyBaseExt> cache(
|
||||
[](const JKQTMathTextCacheKeyBaseExt& key) {
|
||||
const QFontMetricsF fm(key.f, key.pd);
|
||||
return fm.ascent();
|
||||
});
|
||||
|
||||
return cache.get_inline(f, pd);
|
||||
}
|
||||
|
||||
qreal JKQTMathTextGetFontDescent(const QFont &f, QPaintDevice *pd)
|
||||
{
|
||||
static JKQTPDataCache<qreal,JKQTMathTextCacheKeyBase,true,JKQTMathTextCacheKeyBaseExt> cache(
|
||||
[](const JKQTMathTextCacheKeyBaseExt& key) {
|
||||
const QFontMetricsF fm(key.f, key.pd);
|
||||
return fm.descent();
|
||||
});
|
||||
|
||||
return cache.get_inline(f, pd);
|
||||
}
|
||||
|
||||
qreal JKQTMathTextGetFontHeight(const QFont &f, QPaintDevice *pd)
|
||||
{
|
||||
static JKQTPDataCache<qreal,JKQTMathTextCacheKeyBase,true,JKQTMathTextCacheKeyBaseExt> cache(
|
||||
[](const JKQTMathTextCacheKeyBaseExt& key) {
|
||||
const QFontMetricsF fm(key.f, key.pd);
|
||||
return fm.height();
|
||||
});
|
||||
|
||||
return cache.get_inline(f, pd);
|
||||
}
|
||||
|
||||
qreal JKQTMathTextGetFontLineWidth(const QFont &f, QPaintDevice *pd)
|
||||
{
|
||||
static JKQTPDataCache<qreal,JKQTMathTextCacheKeyBase,true,JKQTMathTextCacheKeyBaseExt> cache(
|
||||
[](const JKQTMathTextCacheKeyBaseExt& key) {
|
||||
const QFontMetricsF fm(key.f, key.pd);
|
||||
return fm.lineWidth();
|
||||
});
|
||||
|
||||
return cache.get_inline(f, pd);
|
||||
}
|
||||
|
||||
qreal JKQTMathTextGetFontLeading(const QFont &f, QPaintDevice *pd)
|
||||
{
|
||||
static JKQTPDataCache<qreal,JKQTMathTextCacheKeyBase,true,JKQTMathTextCacheKeyBaseExt> cache(
|
||||
[](const JKQTMathTextCacheKeyBaseExt& key) {
|
||||
const QFontMetricsF fm(key.f, key.pd);
|
||||
return fm.leading();
|
||||
});
|
||||
|
||||
return cache.get_inline(f, pd);
|
||||
}
|
||||
|
||||
qreal JKQTMathTextGetFontLineSpacing(const QFont &f, QPaintDevice *pd)
|
||||
{
|
||||
static JKQTPDataCache<qreal,JKQTMathTextCacheKeyBase,true,JKQTMathTextCacheKeyBaseExt> cache(
|
||||
[](const JKQTMathTextCacheKeyBaseExt& key) {
|
||||
const QFontMetricsF fm(key.f, key.pd);
|
||||
return fm.lineSpacing();
|
||||
});
|
||||
|
||||
return cache.get_inline(f, pd);
|
||||
}
|
||||
|
||||
qreal JKQTMathTextGetFontStrikoutPos(const QFont &f, QPaintDevice *pd)
|
||||
{
|
||||
static JKQTPDataCache<qreal,JKQTMathTextCacheKeyBase,true,JKQTMathTextCacheKeyBaseExt> cache(
|
||||
[](const JKQTMathTextCacheKeyBaseExt& key) {
|
||||
const QFontMetricsF fm(key.f, key.pd);
|
||||
return fm.strikeOutPos();
|
||||
});
|
||||
|
||||
return cache.get_inline(f, pd);
|
||||
}
|
||||
|
||||
QFont JKQTMathTextGetNonItalic(const QFont &font)
|
||||
@ -1048,12 +1208,12 @@ JKQTMathTextBlackboradDrawingMode String2JKQTMathTextBlackboradDrawingMode(QStri
|
||||
|
||||
void JKQTMathTextDrawStringSimBlackboard(QPainter &painter, const QFont &f, const QColor& color, double x, double y, const QString &txt)
|
||||
{
|
||||
const QFontMetricsF fm(f, painter.device());
|
||||
const QPen p(color, fm.lineWidth()/4.0, Qt::SolidLine);
|
||||
const qreal lw=JKQTMathTextGetFontLineWidth(f, painter.device());
|
||||
const QPen p(color, lw/4.0, Qt::SolidLine);
|
||||
painter.setPen(p);
|
||||
QPainterPath path;
|
||||
path.addText(QPointF(x, y), f, txt);
|
||||
path.addText(QPointF(x+fm.lineWidth()/2.0, y), f, txt);
|
||||
path.addText(QPointF(x+lw/2.0, y), f, txt);
|
||||
painter.drawPath(path);
|
||||
}
|
||||
|
||||
@ -1074,3 +1234,4 @@ JKQTMathTextLineSpacingMode String2JKQTMathTextLineSpacingMode(QString tokenName
|
||||
if (tokenName=="minimal" || tokenName=="min" || tokenName=="minimum") return MTSMMinimalSpacing;
|
||||
return MTSMDefaultSpacing;
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,8 @@
|
||||
#include <QHash>
|
||||
#include <QPainterPath>
|
||||
#include <QtMath>
|
||||
|
||||
#include <QFontMetrics>
|
||||
#include <QFontMetricsF>
|
||||
class JKQTMathText; // forward
|
||||
|
||||
|
||||
@ -471,41 +472,173 @@ JKQTMATHTEXT_LIB_EXPORT QPainterPath JKQTMathTextMakeDArrow(double x, double y,
|
||||
*/
|
||||
JKQTMATHTEXT_LIB_EXPORT void JKQTMathTextDrawStringSimBlackboard(QPainter& painter, const QFont& f, const QColor &color, double x, double y, const QString& txt);
|
||||
|
||||
struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextTBRData {
|
||||
explicit JKQTMathTextTBRData(const QFont& f, const QString& text, QPaintDevice *pd);
|
||||
QFontMetricsF fm;
|
||||
QString text;
|
||||
QRectF tbr;
|
||||
QFont f;
|
||||
int ldpiX, ldpiY, pdpiX, pdpiY;
|
||||
//QPaintDevice *pd;
|
||||
|
||||
bool operator==(const JKQTMathTextTBRData& other) const;
|
||||
};
|
||||
|
||||
struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextTBRDataH {
|
||||
explicit JKQTMathTextTBRDataH(const QFont& f, const QString& text, QPaintDevice *pd);
|
||||
QString text;
|
||||
QFont f;
|
||||
int ldpiX, ldpiY, pdpiX, pdpiY;
|
||||
|
||||
bool operator==(const JKQTMathTextTBRDataH& other) const;
|
||||
};
|
||||
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
|
||||
inline size_t qHash(const JKQTMathTextTBRDataH& data, size_t /*seed=0*/) {
|
||||
#else
|
||||
inline uint qHash(const JKQTMathTextTBRDataH& data) {
|
||||
#endif
|
||||
return qHash(data.f.family())+qHash(data.text);
|
||||
}
|
||||
|
||||
|
||||
/** \brief calculates the tight bounding rectangle around \a text, uses internal hashing to not redo a calculation that has already been performed
|
||||
/** \brief calculates the tight bounding rectangle around \a text
|
||||
* (from <a href="https://doc.qt.io/qt/qfontmetricsf.html#tightBoundingRect">QFontMetricsF::tightBoundingRect()</a>),
|
||||
* uses internal (thread-local) hashing to not redo a calculation that has already been performed
|
||||
* \ingroup jkqtmathtext_tools
|
||||
*
|
||||
* \param fm font the text should be set in
|
||||
* \param text the text of which the properties are calculated
|
||||
* \param pd (or \c nullptr) the currently used <a href="https://doc.qt.io/qt-6/qpaintdevice.html">QPaintDevice</a>
|
||||
* (e.g. from <a href="https://doc.qt.io/qt/qpainter.html#device">QPainter::device()</a> )
|
||||
*
|
||||
* \note This function is thread-safe and uses the same cache for all threads (so they profit from eachother)
|
||||
*/
|
||||
JKQTMATHTEXT_LIB_EXPORT QRectF JKQTMathTextGetTightBoundingRect(const QFont &fm, const QString& text, QPaintDevice *pd);
|
||||
|
||||
/** \brief calculates the bounding rectangle around \a text
|
||||
* (from (using <a href="https://doc.qt.io/qt/qfontmetricsf.html#boundingRect">QFontMetricsF::boundingRect()</a>),
|
||||
* uses internal hashing to not redo a calculation that has already been performed
|
||||
* \ingroup jkqtmathtext_tools
|
||||
*
|
||||
* \param fm font the text should be set in
|
||||
* \param text the text of which the properties are calculated
|
||||
* \param pd (or \c nullptr) the currently used <a href="https://doc.qt.io/qt-6/qpaintdevice.html">QPaintDevice</a>
|
||||
* (e.g. from <a href="https://doc.qt.io/qt/qpainter.html#device">QPainter::device()</a> )
|
||||
*
|
||||
* \note This function is thread-safe and uses the same cache for all threads (so they profit from eachother)
|
||||
*/
|
||||
JKQTMATHTEXT_LIB_EXPORT QRectF JKQTMathTextGetBoundingRect(const QFont &fm, const QString& text, QPaintDevice *pd);
|
||||
|
||||
/** \brief calculates the horizontal advance of \a text
|
||||
* (from <a href="https://doc.qt.io/qt/qfontmetricsf.html#horizontalAdvance">QFontMetricsF::horizontalAdvance()</a>
|
||||
* or \c QFontMetricsF::width() if it is not yet available in your Qt version),
|
||||
* uses internal hashing to not redo a calculation that has already been performed
|
||||
* \ingroup jkqtmathtext_tools
|
||||
*
|
||||
* \param fm font the text should be set in
|
||||
* \param text the text of which the properties are calculated
|
||||
* \param pd (or \c nullptr) the currently used <a href="https://doc.qt.io/qt-6/qpaintdevice.html">QPaintDevice</a>
|
||||
* (e.g. from <a href="https://doc.qt.io/qt/qpainter.html#device">QPainter::device()</a> )
|
||||
*
|
||||
* \note This function is thread-safe and uses the same cache for all threads (so they profit from eachother)
|
||||
*/
|
||||
JKQTMATHTEXT_LIB_EXPORT qreal JKQTMathTextGetHorAdvance(const QFont &fm, const QString& text, QPaintDevice *pd);
|
||||
|
||||
/** \brief calculates the left bearing of \a text
|
||||
* (from <a href="https://doc.qt.io/qt-6/qfontmetricsf.html#leftBearing">QFontMetricsF::leftBearing()</a>),
|
||||
* uses internal hashing to not redo a calculation that has already been performed
|
||||
* \ingroup jkqtmathtext_tools
|
||||
*
|
||||
* \param fm font the text should be set in
|
||||
* \param text the character of which the properties are calculated
|
||||
* \param pd (or \c nullptr) the currently used <a href="https://doc.qt.io/qt-6/qpaintdevice.html">QPaintDevice</a>
|
||||
* (e.g. from <a href="https://doc.qt.io/qt/qpainter.html#device">QPainter::device()</a> )
|
||||
*
|
||||
* \note This function is thread-safe and uses the same cache for all threads (so they profit from eachother)
|
||||
*/
|
||||
JKQTMATHTEXT_LIB_EXPORT qreal JKQTMathTextGetLeftBearing(const QFont &fm, const QChar& text, QPaintDevice *pd);
|
||||
|
||||
/** \brief calculates the right bearing of \a text
|
||||
* (from <a href="https://doc.qt.io/qt-6/qfontmetricsf.html#rightBearing">QFontMetricsF::rightBearing()</a>),
|
||||
* uses internal hashing to not redo a calculation that has already been performed
|
||||
* \ingroup jkqtmathtext_tools
|
||||
*
|
||||
* \param fm font the text should be set in
|
||||
* \param text the character of which the properties are calculated
|
||||
* \param pd (or \c nullptr) the currently used <a href="https://doc.qt.io/qt-6/qpaintdevice.html">QPaintDevice</a>
|
||||
* (e.g. from <a href="https://doc.qt.io/qt/qpainter.html#device">QPainter::device()</a> )
|
||||
*
|
||||
* \note This function is thread-safe and uses the same cache for all threads (so they profit from eachother)
|
||||
*/
|
||||
JKQTMATHTEXT_LIB_EXPORT qreal JKQTMathTextGetRightBearing(const QFont &fm, const QChar& text, QPaintDevice *pd);
|
||||
|
||||
|
||||
/** \brief calculates the strikeout-pos of \a font
|
||||
* (from <a href="https://doc.qt.io/qt-6/qfontmetricsf.html#strikeoutPos">QFontMetricsF::strikeoutPos()</a>),
|
||||
* uses internal hashing to not redo a calculation that has already been performed
|
||||
* \ingroup jkqtmathtext_tools
|
||||
*
|
||||
* \param fm font for which to calculate
|
||||
* \param pd (or \c nullptr) the currently used <a href="https://doc.qt.io/qt-6/qpaintdevice.html">QPaintDevice</a>
|
||||
* (e.g. from <a href="https://doc.qt.io/qt/qpainter.html#device">QPainter::device()</a> )
|
||||
*
|
||||
* \note This function is thread-safe and uses the same cache for all threads (so they profit from eachother)
|
||||
*/
|
||||
JKQTMATHTEXT_LIB_EXPORT qreal JKQTMathTextGetFontStrikoutPos(const QFont &fm, QPaintDevice *pd);
|
||||
|
||||
/** \brief calculates the line width of \a font
|
||||
* (from <a href="https://doc.qt.io/qt-6/qfontmetricsf.html#lineWidth">QFontMetricsF::lineWidth()</a>),
|
||||
* uses internal hashing to not redo a calculation that has already been performed
|
||||
* \ingroup jkqtmathtext_tools
|
||||
*
|
||||
* \param fm font for which to calculate
|
||||
* \param pd (or \c nullptr) the currently used <a href="https://doc.qt.io/qt-6/qpaintdevice.html">QPaintDevice</a>
|
||||
* (e.g. from <a href="https://doc.qt.io/qt/qpainter.html#device">QPainter::device()</a> )
|
||||
*
|
||||
* \note This function is thread-safe and uses the same cache for all threads (so they profit from eachother)
|
||||
*/
|
||||
JKQTMATHTEXT_LIB_EXPORT qreal JKQTMathTextGetFontLineWidth(const QFont &fm, QPaintDevice *pd);
|
||||
|
||||
/** \brief calculates the ascent of \a font
|
||||
* (from <a href="https://doc.qt.io/qt-6/qfontmetricsf.html#ascent">QFontMetricsF::ascent()</a>),
|
||||
* uses internal hashing to not redo a calculation that has already been performed
|
||||
* \ingroup jkqtmathtext_tools
|
||||
*
|
||||
* \param fm font for which to calculate
|
||||
* \param pd (or \c nullptr) the currently used <a href="https://doc.qt.io/qt-6/qpaintdevice.html">QPaintDevice</a>
|
||||
* (e.g. from <a href="https://doc.qt.io/qt/qpainter.html#device">QPainter::device()</a> )
|
||||
*
|
||||
* \note This function is thread-safe and uses the same cache for all threads (so they profit from eachother)
|
||||
*/
|
||||
JKQTMATHTEXT_LIB_EXPORT qreal JKQTMathTextGetFontAscent(const QFont &fm, QPaintDevice *pd);
|
||||
|
||||
/** \brief calculates the descent of \a font
|
||||
* (from <a href="https://doc.qt.io/qt-6/qfontmetricsf.html#descent">QFontMetricsF::descent()</a>),
|
||||
* uses internal hashing to not redo a calculation that has already been performed
|
||||
* \ingroup jkqtmathtext_tools
|
||||
*
|
||||
* \param fm font for which to calculate
|
||||
* \param pd (or \c nullptr) the currently used <a href="https://doc.qt.io/qt-6/qpaintdevice.html">QPaintDevice</a>
|
||||
* (e.g. from <a href="https://doc.qt.io/qt/qpainter.html#device">QPainter::device()</a> )
|
||||
*
|
||||
* \note This function is thread-safe and uses the same cache for all threads (so they profit from eachother)
|
||||
*/
|
||||
JKQTMATHTEXT_LIB_EXPORT qreal JKQTMathTextGetFontDescent(const QFont &fm, QPaintDevice *pd);
|
||||
|
||||
|
||||
/** \brief calculates the height of \a font
|
||||
* (from <a href="https://doc.qt.io/qt-6/qfontmetricsf.html#height">QFontMetricsF::height()</a>),
|
||||
* uses internal hashing to not redo a calculation that has already been performed
|
||||
* \ingroup jkqtmathtext_tools
|
||||
*
|
||||
* \param fm font for which to calculate
|
||||
* \param pd (or \c nullptr) the currently used <a href="https://doc.qt.io/qt-6/qpaintdevice.html">QPaintDevice</a>
|
||||
* (e.g. from <a href="https://doc.qt.io/qt/qpainter.html#device">QPainter::device()</a> )
|
||||
*
|
||||
* \note This function is thread-safe and uses the same cache for all threads (so they profit from eachother)
|
||||
*/
|
||||
JKQTMATHTEXT_LIB_EXPORT qreal JKQTMathTextGetFontHeight(const QFont &fm, QPaintDevice *pd);
|
||||
|
||||
/** \brief calculates the leading of \a font
|
||||
* (from <a href="https://doc.qt.io/qt-6/qfontmetricsf.html#leading">QFontMetricsF::leading()</a>),
|
||||
* uses internal hashing to not redo a calculation that has already been performed
|
||||
* \ingroup jkqtmathtext_tools
|
||||
*
|
||||
* \param fm font for which to calculate
|
||||
* \param pd (or \c nullptr) the currently used <a href="https://doc.qt.io/qt-6/qpaintdevice.html">QPaintDevice</a>
|
||||
* (e.g. from <a href="https://doc.qt.io/qt/qpainter.html#device">QPainter::device()</a> )
|
||||
*
|
||||
* \note This function is thread-safe and uses the same cache for all threads (so they profit from eachother)
|
||||
*/
|
||||
JKQTMATHTEXT_LIB_EXPORT qreal JKQTMathTextGetFontLeading(const QFont &fm, QPaintDevice *pd);
|
||||
|
||||
/** \brief calculates the line spacing of \a font
|
||||
* (from <a href="https://doc.qt.io/qt-6/qfontmetricsf.html#lineSpacing">QFontMetricsF::lineSpacing()</a>),
|
||||
* uses internal hashing to not redo a calculation that has already been performed
|
||||
* \ingroup jkqtmathtext_tools
|
||||
*
|
||||
* \param fm font for which to calculate
|
||||
* \param pd (or \c nullptr) the currently used <a href="https://doc.qt.io/qt-6/qpaintdevice.html">QPaintDevice</a>
|
||||
* (e.g. from <a href="https://doc.qt.io/qt/qpainter.html#device">QPainter::device()</a> )
|
||||
*
|
||||
* \note This function is thread-safe and uses the same cache for all threads (so they profit from eachother)
|
||||
*/
|
||||
JKQTMATHTEXT_LIB_EXPORT qreal JKQTMathTextGetFontLineSpacing(const QFont &fm, QPaintDevice *pd);
|
||||
|
||||
|
||||
/** \brief returns a copy of \a f, but with the italic-property set to \c false
|
||||
* \ingroup jkqtmathtext_tools
|
||||
*/
|
||||
|
@ -24,8 +24,8 @@
|
||||
#include "jkqtmathtext/jkqtmathtext.h"
|
||||
#include "jkqtcommon/jkqtpcodestructuring.h"
|
||||
#include "jkqtcommon/jkqtpstringtools.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
#include <cmath>
|
||||
#include <QFontMetricsF>
|
||||
#include <QDebug>
|
||||
#include <QFontDatabase>
|
||||
#include <QFontInfo>
|
||||
@ -60,9 +60,9 @@ JKQTMathTextNodeSize JKQTMathTextBoxInstructionNode::getSizeInternal(QPainter& p
|
||||
inst.modifier(ev, getParameters());
|
||||
const QPen p=inst.pen(ev, getParameters(), parentMathText);
|
||||
const QBrush b=inst.brush(ev, getParameters(), parentMathText);
|
||||
const QFontMetricsF fmNonItalic(JKQTMathTextGetNonItalic(currentEv.getFont(parentMathText)), painter.device());
|
||||
const QFont fNonItalic=JKQTMathTextGetNonItalic(currentEv.getFont(parentMathText));
|
||||
const double lw=p.widthF();
|
||||
const double padding=inst.paddingFactor*fmNonItalic.tightBoundingRect("x").width();
|
||||
const double padding=inst.paddingFactor*JKQTMathTextGetBoundingRect(fNonItalic, "x", painter.device()).width();
|
||||
|
||||
const JKQTMathTextNodeSize cs=getChild()->getSize(painter, ev);
|
||||
JKQTMathTextNodeSize s;
|
||||
@ -74,6 +74,9 @@ JKQTMathTextNodeSize JKQTMathTextBoxInstructionNode::getSizeInternal(QPainter& p
|
||||
}
|
||||
|
||||
double JKQTMathTextBoxInstructionNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv) const {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextBoxInstructionNode[]::draw()"));
|
||||
#endif
|
||||
doDrawBoxes(painter, x, y, currentEv);
|
||||
JKQTMathTextEnvironment ev=currentEv;
|
||||
|
||||
@ -81,10 +84,10 @@ double JKQTMathTextBoxInstructionNode::draw(QPainter& painter, double x, double
|
||||
inst.modifier(ev, getParameters());
|
||||
const QPen p=inst.pen(ev, getParameters(), parentMathText);
|
||||
const QBrush b=inst.brush(ev, getParameters(), parentMathText);
|
||||
const QFontMetricsF fmNonItalic(JKQTMathTextGetNonItalic(currentEv.getFont(parentMathText)), painter.device());
|
||||
const QFont fNonItalic=JKQTMathTextGetNonItalic(currentEv.getFont(parentMathText));
|
||||
const double lw=p.widthF();
|
||||
const double padding=inst.paddingFactor*fmNonItalic.tightBoundingRect("x").width();
|
||||
const double rr=inst.roundingFactor*fmNonItalic.tightBoundingRect("x").width();
|
||||
const double padding=inst.paddingFactor*JKQTMathTextGetBoundingRect(fNonItalic, "x", painter.device()).width();
|
||||
const double rr=inst.roundingFactor*JKQTMathTextGetBoundingRect(fNonItalic, "x", painter.device()).width();
|
||||
const JKQTMathTextNodeSize cs=getChild()->getSize(painter, ev);
|
||||
|
||||
{
|
||||
@ -116,10 +119,10 @@ bool JKQTMathTextBoxInstructionNode::toHtml(QString &html, JKQTMathTextEnvironme
|
||||
inst.modifier(ev, getParameters());
|
||||
const QPen p=inst.pen(ev, getParameters(), parentMathText);
|
||||
const QBrush b=inst.brush(ev, getParameters(), parentMathText);
|
||||
const QFontMetricsF fmNonItalic(JKQTMathTextGetNonItalic(currentEv.getFont(parentMathText)));
|
||||
const QFont fNonItalic=JKQTMathTextGetNonItalic(currentEv.getFont(parentMathText));
|
||||
//const double lw=p.widthF();
|
||||
const double padding=inst.paddingFactor*fmNonItalic.tightBoundingRect("x").width();
|
||||
//const double rr=inst.roundingFactor*fmNonItalic.tightBoundingRect("x").width();
|
||||
const double padding=inst.paddingFactor*JKQTMathTextGetBoundingRect(fNonItalic, "x", nullptr).width();
|
||||
//const double rr=inst.roundingFactor*JKQTMathTextGetBoundingRect(fNonItalic, "x", painter.device()).width();
|
||||
QString s=QString("padding: %1px").arg(padding);
|
||||
if (p!=Qt::NoPen) {
|
||||
if (s.size()>0 && s.right(2)!="; ") s=s+"; ";
|
||||
@ -310,7 +313,7 @@ JKQTMathTextBoxInstructionNode::InstructionProperties::ModifyEnvironmentFunctor
|
||||
[](JKQTMathTextEnvironment& /*ev*/, const QStringList& /*parameters*/){};
|
||||
|
||||
JKQTMathTextBoxInstructionNode::InstructionProperties::GetBoxPenFunctor JKQTMathTextBoxInstructionNode::InstructionProperties::DefaultPen=
|
||||
[](JKQTMathTextEnvironment& ev, const QStringList& /*parameters*/, JKQTMathText* parent){ return QPen(ev.color, QFontMetricsF(ev.getFont(parent)).lineWidth(), Qt::SolidLine); };
|
||||
[](JKQTMathTextEnvironment& ev, const QStringList& /*parameters*/, JKQTMathText* parent){ return QPen(ev.color, JKQTMathTextGetFontLineWidth(ev.getFont(parent),nullptr), Qt::SolidLine); };
|
||||
|
||||
JKQTMathTextBoxInstructionNode::InstructionProperties::GetBoxPenFunctor JKQTMathTextBoxInstructionNode::InstructionProperties::NoPen=
|
||||
[](JKQTMathTextEnvironment& /*ev*/, const QStringList& /*parameters*/, JKQTMathText* /*parent*/){ return Qt::NoPen; };
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "jkqtmathtext/jkqtmathtext.h"
|
||||
#include "jkqtcommon/jkqtpcodestructuring.h"
|
||||
#include "jkqtcommon/jkqtpstringtools.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
#include <cmath>
|
||||
#include <QFontMetricsF>
|
||||
#include <QDebug>
|
||||
@ -55,8 +56,8 @@ JKQTMathTextBraceNode::NodeSize JKQTMathTextBraceNode::getSizeInternalAndBrace(Q
|
||||
{
|
||||
NodeSize s;
|
||||
const NodeSize childSize=getChild()->getSize(painter, currentEv);
|
||||
const QFontMetricsF fm(currentEv.getFont(parentMathText), painter.device());
|
||||
const double minChildHeight=fm.tightBoundingRect("l").height();
|
||||
const QFont f=currentEv.getFont(parentMathText);
|
||||
const double minChildHeight=JKQTMathTextGetTightBoundingRect(f, "l", painter.device()).height();
|
||||
|
||||
double cAscentAboveStrike=0;
|
||||
double cDescentBelowStrike=0;
|
||||
@ -84,13 +85,16 @@ JKQTMathTextBraceNode::NodeSize JKQTMathTextBraceNode::getSizeInternalAndBrace(Q
|
||||
}
|
||||
|
||||
double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv) const {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextBraceNode[]::draw()"));
|
||||
#endif
|
||||
//std::cout<<"drawing brace-node: '"<<openbrace.toStdString()<<"' ... '"<<closebrace.toStdString()<<"'\n";
|
||||
|
||||
const NodeSize nodesize=getSizeInternalAndBrace(painter, currentEv);
|
||||
doDrawBoxes(painter, x, y, nodesize);
|
||||
const QFontMetricsF fm(currentEv.getFont(parentMathText), painter.device());
|
||||
const QFont f=currentEv.getFont(parentMathText);
|
||||
|
||||
const double lw=fm.lineWidth();
|
||||
const double lw=JKQTMathTextGetFontLineWidth(f, painter.device());
|
||||
|
||||
double xnew=x;
|
||||
|
||||
@ -360,7 +364,6 @@ double JKQTMathTextBraceNode::draw(QPainter& painter, double x, double y, JKQTMa
|
||||
}
|
||||
}
|
||||
|
||||
//qDebug()<<" ==> "<<bc<<fm.boundingRect(bc).width();
|
||||
return xnew;
|
||||
}
|
||||
|
||||
@ -466,20 +469,20 @@ JKQTMathTextBraceNode::NodeSize::NodeSize(const NodeSize &other):
|
||||
|
||||
void JKQTMathTextBraceNode::calcBraceSizes(NodeSize& out, QPainter &painter, const JKQTMathTextEnvironment &ev, const JKQTMathTextNodeSize &childSize) const
|
||||
{
|
||||
const QFontMetricsF fm(ev.getFont(parentMathText), painter.device());
|
||||
const QSizeF openBraceS=calcBraceSize(fm, openbrace, childSize);
|
||||
const QSizeF closeBraceS=calcBraceSize(fm, closebrace, childSize);
|
||||
const QFont f=ev.getFont(parentMathText);
|
||||
const QSizeF openBraceS=calcBraceSize(f, painter.device(), openbrace, childSize);
|
||||
const QSizeF closeBraceS=calcBraceSize(f, painter.device(), closebrace, childSize);
|
||||
out.openBraceWidth=openBraceS.width();
|
||||
out.openBraceHeight=openBraceS.width();
|
||||
out.closeBraceWidth=closeBraceS.width();
|
||||
out.closeBraceHeight=closeBraceS.width();
|
||||
}
|
||||
|
||||
QSizeF JKQTMathTextBraceNode::calcBraceSize(const QFontMetricsF &fm, JKQTMathTextBraceType bracetype, const JKQTMathTextNodeSize &childSize) const
|
||||
QSizeF JKQTMathTextBraceNode::calcBraceSize(const QFont &f, QPaintDevice *pd, JKQTMathTextBraceType bracetype, const JKQTMathTextNodeSize &childSize) const
|
||||
{
|
||||
double braceWidth=0.0;
|
||||
double braceHeight=0.0;
|
||||
const double lw=fm.lineWidth();
|
||||
const double lw=JKQTMathTextGetFontLineWidth(f, pd);
|
||||
const double dblline_distance=2.0*lw;
|
||||
braceHeight=childSize.overallHeight*parentMathText->getBraceFactor();
|
||||
braceWidth=lw*5.0;
|
||||
@ -489,7 +492,7 @@ QSizeF JKQTMathTextBraceNode::calcBraceSize(const QFontMetricsF &fm, JKQTMathTex
|
||||
if (bracetype==MTBTSingleLine) braceWidth=3.0*lw;
|
||||
if (bracetype==MTBTSquareBracket || bracetype==MTBTCeilBracket || bracetype==MTBTFloorBracket) braceWidth=7.0*lw;
|
||||
|
||||
const double overSizeFactor=braceHeight/fm.height();
|
||||
const double overSizeFactor=braceHeight/JKQTMathTextGetFontHeight(f, pd);
|
||||
if (overSizeFactor>1.2) braceWidth=braceWidth*sqrt(overSizeFactor);
|
||||
|
||||
return QSizeF(braceWidth, braceHeight);
|
||||
|
@ -101,7 +101,7 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextBraceNode: public JKQTMathTextSingleCh
|
||||
*
|
||||
* \return width and hieght of the brace
|
||||
*/
|
||||
QSizeF calcBraceSize(const QFontMetricsF& fm, JKQTMathTextBraceType bracetype, const JKQTMathTextNodeSize &childSize) const;
|
||||
QSizeF calcBraceSize(const QFont& fm, QPaintDevice* pd, JKQTMathTextBraceType bracetype, const JKQTMathTextNodeSize &childSize) const;
|
||||
};
|
||||
|
||||
#endif // JKQTMATHTEXTBRACENODE_H
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "jkqtmathtext/jkqtmathtext.h"
|
||||
#include "jkqtcommon/jkqtpcodestructuring.h"
|
||||
#include "jkqtcommon/jkqtpstringtools.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
#include <cmath>
|
||||
#include <QFontMetricsF>
|
||||
#include <QDebug>
|
||||
@ -133,15 +134,15 @@ JKQTMathTextNodeSize JKQTMathTextDecoratedNode::getSizeInternal(QPainter& painte
|
||||
JKQTMathTextNodeSize cs=getChild()->getSize(painter, ev);
|
||||
const double cDescent=cs.getDescent();
|
||||
const QFont font=ev.getFont(parentMathText);
|
||||
const QFontMetricsF fm(font, painter.device());
|
||||
const double decoSeparation=parentMathText->getDecorationSeparationFactor()*fm.ascent();
|
||||
const double deco_height=parentMathText->getDecorationHeightFactor()*fm.ascent();
|
||||
const double fascent=JKQTMathTextGetFontAscent(font, painter.device());
|
||||
const double decoSeparation=parentMathText->getDecorationSeparationFactor()*fascent;
|
||||
const double deco_height=parentMathText->getDecorationHeightFactor()*fascent;
|
||||
const double deco_ypos=cs.baselineHeight+decoSeparation;
|
||||
const double decoAboveAscent_ypos=fm.ascent()+decoSeparation;
|
||||
const double decoAboveAscent_ypos=fascent+decoSeparation;
|
||||
const double decobelow_ypos=cDescent+decoSeparation;
|
||||
const double italic_xcorrection=getNonItalicXCorretion(painter, cs.width, ev, getChild());
|
||||
const double deco_miniwidth=((decoration==MTDtilde||decoration==MTDbreve)?fm.boundingRect("~").width():fm.boundingRect("^").width())-italic_xcorrection;
|
||||
const double linewidth=qMax(parentMathText->ABS_MIN_LINEWIDTH, fm.lineWidth());
|
||||
const double deco_miniwidth=((decoration==MTDtilde||decoration==MTDbreve)?JKQTMathTextGetBoundingRect(font,"~",painter.device()).width():JKQTMathTextGetBoundingRect(font,"^",painter.device()).width())-italic_xcorrection;
|
||||
const double linewidth=qMax(parentMathText->ABS_MIN_LINEWIDTH, JKQTMathTextGetFontLineWidth(font, painter.device()));
|
||||
|
||||
|
||||
|
||||
@ -227,20 +228,24 @@ const QHash<QString, JKQTMathTextDecoratedNode::DecorationType>& JKQTMathTextDec
|
||||
}
|
||||
|
||||
double JKQTMathTextDecoratedNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv) const {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextDecoratedNode[]::draw()"));
|
||||
#endif
|
||||
doDrawBoxes(painter, x, y, currentEv);
|
||||
JKQTMathTextEnvironment ev=currentEv;
|
||||
auto cs=getChild()->getSize(painter, ev);
|
||||
const double cDescent=cs.overallHeight-cs.baselineHeight;
|
||||
const QFont font=ev.getFont(parentMathText);
|
||||
const QFontMetricsF fm(font, painter.device());
|
||||
const double width_X=fm.boundingRect("X").width();
|
||||
const double width_x=fm.boundingRect("x").width();
|
||||
const double width_dot=fm.boundingRect(".").width()/2.0;
|
||||
const double decoSeparation=parentMathText->getDecorationSeparationFactor()*fm.ascent();
|
||||
const double linewidth=qMax(parentMathText->ABS_MIN_LINEWIDTH, fm.lineWidth());
|
||||
const double width_X=JKQTMathTextGetBoundingRect(font,"X",painter.device()).width();
|
||||
const double width_x=JKQTMathTextGetBoundingRect(font,"x",painter.device()).width();
|
||||
const double width_dot=JKQTMathTextGetBoundingRect(font,".",painter.device()).width()/2.0;
|
||||
const double ascent=JKQTMathTextGetFontLineWidth(font, painter.device());
|
||||
const double decoSeparation=parentMathText->getDecorationSeparationFactor()*ascent;
|
||||
const double linewidth=qMax(parentMathText->ABS_MIN_LINEWIDTH, JKQTMathTextGetFontLineWidth(font, painter.device()));
|
||||
const double linewidthArrow=linewidth*0.65;
|
||||
const double deco_height=parentMathText->getDecorationHeightFactor()*fm.ascent();
|
||||
const double decoAboveAscent_ypos=y-fm.ascent()-decoSeparation;
|
||||
const double deco_height=parentMathText->getDecorationHeightFactor()*ascent;
|
||||
const double decoAboveAscent_ypos=y-ascent-decoSeparation;
|
||||
const double strike_ypos=y-cs.baselineHeight/2.0;
|
||||
const double decobelow_ypos=y+cDescent+decoSeparation;
|
||||
const double italic_xcorrection=getNonItalicXCorretion(painter, cs.width, ev, getChild());
|
||||
@ -249,7 +254,7 @@ double JKQTMathTextDecoratedNode::draw(QPainter& painter, double x, double y, JK
|
||||
const double deco_vecwidth=width_x*0.25;
|
||||
const double deco_vecheight=deco_height*0.5;
|
||||
const double deco_accentwidth=deco_height/4.0;
|
||||
const double deco_miniwidth=((decoration==MTDtilde||decoration==MTDbreve)?fm.boundingRect("j").width():fm.boundingRect("^").width())-italic_xcorrection;
|
||||
const double deco_miniwidth=((decoration==MTDtilde||decoration==MTDbreve)?JKQTMathTextGetBoundingRect(font,"~",painter.device()).width():JKQTMathTextGetBoundingRect(font,"^",painter.device()).width())-italic_xcorrection;
|
||||
const double decotop_xcenter=x+italic_xcorrection+(cs.width-italic_xcorrection)/2.0;
|
||||
const double decotop_xstart=decotop_xcenter-deco_width/2.0+linewidth/2.0;
|
||||
const double decotop_xend=decotop_xcenter+deco_width/2.0-linewidth/2.0;
|
||||
@ -280,7 +285,7 @@ double JKQTMathTextDecoratedNode::draw(QPainter& painter, double x, double y, JK
|
||||
auto fDrawFontAccent=[&](QChar aDirect=QChar(), QChar aFallback=QChar()) -> bool {
|
||||
if (!aDirect.isNull() && fm.inFont(aDirect)) {
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
const QRectF tbra=fm.tightBoundingRect(aDirect);
|
||||
const QRectF tbra=JKQTMathTextGetBoundingRect(font, aDirect, painter.device());
|
||||
painter.translate(decotop_xcenter-tbra.width()/2.0, (deco_ytopcenter+deco_ytoptop)/2.0);
|
||||
//painter.setPen("red");
|
||||
//painter.drawEllipse(0-2,0-2,4,4);
|
||||
@ -298,7 +303,7 @@ double JKQTMathTextDecoratedNode::draw(QPainter& painter, double x, double y, JK
|
||||
}
|
||||
if (!aFallback.isNull() && fm.inFont(aFallback)) {
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
const QRectF tbra=fm.tightBoundingRect(aFallback);
|
||||
const QRectF tbra=JKQTMathTextGetBoundingRect(font, aFallback, painter.device());
|
||||
painter.translate(decotop_xcenter-tbra.width()/2.0, (deco_ytopcenter+deco_ytoptop)/2.0);
|
||||
//painter.setPen("yellow");
|
||||
//painter.drawEllipse(0-2,0-2,4,4);
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "jkqtmathtext/jkqtmathtext.h"
|
||||
#include "jkqtcommon/jkqtpcodestructuring.h"
|
||||
#include "jkqtcommon/jkqtpstringtools.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
#include <cmath>
|
||||
#include <QFontMetricsF>
|
||||
#include <QDebug>
|
||||
@ -128,15 +129,14 @@ JKQTMathTextNodeSize JKQTMathTextFracNode::getSizeInternal(QPainter& painter, JK
|
||||
if (fracmode==MTFMsfrac) fracmode=MTFMstfrac;
|
||||
}
|
||||
const QFont f=currentEv.getFont(parentMathText);
|
||||
const QFontMetricsF fm(f, painter.device());
|
||||
JKQTMathTextEnvironment ev1=currentEv;
|
||||
JKQTMathTextEnvironment ev2=currentEv;
|
||||
|
||||
const double xheight=JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height();
|
||||
const double line_ascent=xheight/2.0;
|
||||
//const double Mheight=JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height();//fm.ascent();
|
||||
//const double Mheight=JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height();
|
||||
const double xwidth=JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).width();
|
||||
const double qheight=JKQTMathTextGetTightBoundingRect(f, "q", painter.device()).height();//fm.ascent();
|
||||
const double qheight=JKQTMathTextGetTightBoundingRect(f, "q", painter.device()).height();
|
||||
const double braceheight=xheight*parentMathText->getUnderbraceBraceSizeXFactor();
|
||||
const double braceseparation=xheight*parentMathText->getUnderbraceSeparationXFactor();
|
||||
|
||||
@ -152,11 +152,11 @@ JKQTMathTextNodeSize JKQTMathTextFracNode::getSizeInternal(QPainter& painter, JK
|
||||
ev2.fontSize=ev2.fontSize*getFracScalingFactor()*0.7;
|
||||
}
|
||||
|
||||
const QFontMetricsF fmev1(ev1.getFont(parentMathText), painter.device());
|
||||
const QRectF AeTBR1=fmev1.tightBoundingRect("A");
|
||||
const QFont fev1=ev1.getFont(parentMathText);
|
||||
const QRectF AeTBR1=JKQTMathTextGetBoundingRect(fev1, "A", painter.device());
|
||||
const double asc1=AeTBR1.height();
|
||||
const QFontMetricsF fmev2(ev2.getFont(parentMathText), painter.device());
|
||||
const QRectF AeTBR2=fmev2.tightBoundingRect("A");
|
||||
const QFont fev2=ev2.getFont(parentMathText);
|
||||
const QRectF AeTBR2=JKQTMathTextGetBoundingRect(fev2, "A", painter.device());
|
||||
const double asc2=AeTBR2.height();
|
||||
|
||||
JKQTMathTextNodeSize size1=child1->getSize(painter, ev1);
|
||||
@ -243,6 +243,9 @@ double JKQTMathTextFracNode::getFracScalingFactor() const
|
||||
}
|
||||
|
||||
double JKQTMathTextFracNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv) const {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextFracNode[]::draw()"));
|
||||
#endif
|
||||
FracType fracmode=this->mode;
|
||||
if (currentEv.isMathTextStyle()) {
|
||||
if (fracmode==MTFMfrac) fracmode=MTFMtfrac;
|
||||
@ -251,14 +254,13 @@ double JKQTMathTextFracNode::draw(QPainter& painter, double x, double y, JKQTMat
|
||||
|
||||
doDrawBoxes(painter, x, y, currentEv);
|
||||
const QFont f=currentEv.getFont(parentMathText);
|
||||
const QFontMetricsF fm(f, painter.device());
|
||||
JKQTMathTextEnvironment ev1=currentEv;
|
||||
JKQTMathTextEnvironment ev2=currentEv;
|
||||
|
||||
|
||||
const double xheight=JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height();
|
||||
const double xwidth=JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).width();
|
||||
const double linewideth=fm.lineWidth();
|
||||
const QRectF tbr_x=JKQTMathTextGetTightBoundingRect(f, "x", painter.device());
|
||||
const double xheight=tbr_x.height();
|
||||
const double xwidth=tbr_x.width();
|
||||
const double linewideth=JKQTMathTextGetFontLineWidth(f, painter.device());
|
||||
const double Mheight=JKQTMathTextGetTightBoundingRect(f, "M", painter.device()).height();//fm.ascent();
|
||||
const double qheight=JKQTMathTextGetTightBoundingRect(f, "q", painter.device()).height();//fm.ascent();
|
||||
const double braceheight=xheight*parentMathText->getUnderbraceBraceSizeXFactor();
|
||||
@ -277,13 +279,14 @@ double JKQTMathTextFracNode::draw(QPainter& painter, double x, double y, JKQTMat
|
||||
}
|
||||
|
||||
|
||||
const QFontMetricsF fmev1(ev1.getFont(parentMathText), painter.device());
|
||||
const QRectF AeTBR1=fmev1.tightBoundingRect("A");
|
||||
const QFont fev1=ev1.getFont(parentMathText);
|
||||
const QRectF AeTBR1=JKQTMathTextGetBoundingRect(fev1, "A", painter.device());
|
||||
const double asc1=AeTBR1.height();
|
||||
const QFontMetricsF fmev2(ev2.getFont(parentMathText), painter.device());
|
||||
const QRectF AeTBR2=fmev2.tightBoundingRect("A");
|
||||
const QFont fev2=ev2.getFont(parentMathText);
|
||||
const QRectF AeTBR2=JKQTMathTextGetBoundingRect(fev2, "A", painter.device());
|
||||
const double asc2=AeTBR2.height();
|
||||
|
||||
|
||||
JKQTMathTextNodeSize size1=child1->getSize(painter, ev1);
|
||||
JKQTMathTextNodeSize size2=child2->getSize(painter, ev2);
|
||||
if (asc1>size1.baselineHeight) {
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "jkqtmathtext/jkqtmathtext.h"
|
||||
#include "jkqtcommon/jkqtpcodestructuring.h"
|
||||
#include "jkqtcommon/jkqtpstringtools.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
#include <cmath>
|
||||
#include <QFontMetricsF>
|
||||
#include <QDebug>
|
||||
@ -63,12 +64,12 @@ JKQTMathTextNodeSize JKQTMathTextHorizontalListNode::getSizeInternal(QPainter& p
|
||||
//bool wasBrace=false;
|
||||
for (int i=0; i<nodes.size(); i++) {
|
||||
const QFont f=currentEv.getFont(parentMathText);
|
||||
const QFontMetricsF fm(f, painter.device());
|
||||
const double subsupershift=JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()*parentMathText->getOperatorsubsuperDistanceFactor();
|
||||
const double subsuperextrawidth=fm.boundingRect('x').width()*parentMathText->getOperatorsubsuperExtraSpaceFactor();
|
||||
const double subsuperSpecialModeAscent=fm.ascent()*parentMathText->getSubsuperModeSelectionBySizeFactor();
|
||||
const double subsuperSpecialModeDecent=fm.descent()*parentMathText->getSubsuperModeSelectionBySizeFactor();
|
||||
const double spaceWidth=fm.boundingRect(' ').width();
|
||||
const auto tbr_x=JKQTMathTextGetTightBoundingRect(f, "x", painter.device());
|
||||
const double subsupershift=tbr_x.height()*parentMathText->getOperatorsubsuperDistanceFactor();
|
||||
const double subsuperextrawidth=tbr_x.width()*parentMathText->getOperatorsubsuperExtraSpaceFactor();
|
||||
const double subsuperSpecialModeAscent=JKQTMathTextGetFontAscent(f, painter.device())*parentMathText->getSubsuperModeSelectionBySizeFactor();
|
||||
const double subsuperSpecialModeDecent=JKQTMathTextGetFontDescent(f, painter.device())*parentMathText->getSubsuperModeSelectionBySizeFactor();
|
||||
const double spaceWidth=JKQTMathTextGetBoundingRect(f, " ", painter.device()).width();
|
||||
|
||||
JKQTMathTextSymbolNode::NodeSize prevNodeSize;
|
||||
JKQTMathTextNodeSize* prevNodeSizePtrForSubscript=nullptr;
|
||||
@ -85,7 +86,7 @@ JKQTMathTextNodeSize JKQTMathTextHorizontalListNode::getSizeInternal(QPainter& p
|
||||
if (shouldUseSpecialSubscriptMode) prevNodeSizePtrForSubscript=&prevNodeSize;
|
||||
if (shouldUseSpecialSuperscriptMode) prevNodeSizePtrForSuperscript=&prevNodeSize;
|
||||
}
|
||||
const double subscript_xcorrection=prevNodeSize.baselineXCorrection+fm.lineWidth()*0.5;
|
||||
const double subscript_xcorrection=prevNodeSize.baselineXCorrection+JKQTMathTextGetFontLineWidth(f, painter.device())*0.5;
|
||||
|
||||
JKQTMathTextSuperscriptNode* nodeI_SuperScript=dynamic_cast<JKQTMathTextSuperscriptNode*>(nodes[i]);
|
||||
JKQTMathTextSubscriptNode* nodeI_SubScript=dynamic_cast<JKQTMathTextSubscriptNode*>(nodes[i]);
|
||||
@ -327,6 +328,9 @@ JKQTMathTextNodeSize JKQTMathTextHorizontalListNode::getSizeInternal(QPainter& p
|
||||
}
|
||||
|
||||
double JKQTMathTextHorizontalListNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment ev) const {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextHorizontalListNode[]::draw()"));
|
||||
#endif
|
||||
JKQTMathTextEnvironment currentEv=ev;
|
||||
doDrawBoxes(painter, x, y, currentEv);
|
||||
double ynew=y;
|
||||
@ -335,11 +339,11 @@ double JKQTMathTextHorizontalListNode::draw(QPainter& painter, double x, double
|
||||
for (int i=0; i<nodes.size(); i++) {
|
||||
bool doDraw=true;
|
||||
const QFont f=currentEv.getFont(parentMathText);
|
||||
const QFontMetricsF fm(f, painter.device());
|
||||
const double subsupershift=JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height()*parentMathText->getOperatorsubsuperDistanceFactor();
|
||||
const double subsuperextrawidth=fm.boundingRect('x').width()*parentMathText->getOperatorsubsuperExtraSpaceFactor();
|
||||
const double subsuperSpecialModeAscent=fm.ascent()*parentMathText->getSubsuperModeSelectionBySizeFactor();
|
||||
const double subsuperSpecialModeDecent=fm.descent()*parentMathText->getSubsuperModeSelectionBySizeFactor();
|
||||
const auto tbr_x=JKQTMathTextGetTightBoundingRect(f, "x", painter.device());
|
||||
const double subsupershift=tbr_x.height()*parentMathText->getOperatorsubsuperDistanceFactor();
|
||||
const double subsuperextrawidth=tbr_x.width()*parentMathText->getOperatorsubsuperExtraSpaceFactor();
|
||||
const double subsuperSpecialModeAscent=JKQTMathTextGetFontAscent(f, painter.device())*parentMathText->getSubsuperModeSelectionBySizeFactor();
|
||||
const double subsuperSpecialModeDecent=JKQTMathTextGetFontDescent(f, painter.device())*parentMathText->getSubsuperModeSelectionBySizeFactor();
|
||||
|
||||
JKQTMathTextSymbolNode::NodeSize prevNodeSize;
|
||||
JKQTMathTextNodeSize* prevNodeSizePtrForSubscript=nullptr;
|
||||
@ -359,7 +363,7 @@ double JKQTMathTextHorizontalListNode::draw(QPainter& painter, double x, double
|
||||
if (shouldUseSpecialSubscriptMode) prevNodeSizePtrForSubscript=&prevNodeSize;
|
||||
if (shouldUseSpecialSuperscriptMode) prevNodeSizePtrForSuperscript=&prevNodeSize;
|
||||
}
|
||||
const double subscript_xcorrection=prevNodeSize.baselineXCorrection+fm.lineWidth()*0.5;
|
||||
const double subscript_xcorrection=prevNodeSize.baselineXCorrection+JKQTMathTextGetFontLineWidth(f, painter.device())*0.5;
|
||||
|
||||
JKQTMathTextSuperscriptNode* nodeI_SuperScript=dynamic_cast<JKQTMathTextSuperscriptNode*>(nodes[i]);
|
||||
JKQTMathTextSubscriptNode* nodeI_SubScript=dynamic_cast<JKQTMathTextSubscriptNode*>(nodes[i]);
|
||||
|
@ -82,9 +82,8 @@ double JKQTMathTextSimpleInstructionNode::draw(QPainter &painter, double x, doub
|
||||
doDrawBoxes(painter, x, y, currentEv);
|
||||
QFont f=currentEv.getFont(parentMathText);
|
||||
f.setStyleStrategy(QFont::PreferDefault);
|
||||
const QFontMetricsF fm(f, painter.device());
|
||||
const QString txt=executeInstruction();
|
||||
const QRectF bb=fm.boundingRect(txt);
|
||||
const QRectF bb=JKQTMathTextGetBoundingRect(f, txt, painter.device());
|
||||
painter.setPen(currentEv.color);
|
||||
painter.setFont(f);
|
||||
painter.drawText(x,y,txt);
|
||||
@ -123,14 +122,13 @@ JKQTMathTextNodeSize JKQTMathTextSimpleInstructionNode::getSizeInternal(QPainter
|
||||
{
|
||||
QFont f=currentEv.getFont(parentMathText);
|
||||
f.setStyleStrategy(QFont::PreferDefault);
|
||||
const QFontMetricsF fm(f, painter.device());
|
||||
const QString txt=executeInstruction();
|
||||
const QRectF bb=fm.boundingRect(txt);
|
||||
const QRectF bb=JKQTMathTextGetBoundingRect(f, txt, painter.device());
|
||||
JKQTMathTextNodeSize s;
|
||||
s.width=bb.width();
|
||||
s.baselineHeight=-bb.y();
|
||||
s.overallHeight=bb.height();
|
||||
s.strikeoutPos=fm.strikeOutPos();
|
||||
s.strikeoutPos=JKQTMathTextGetFontStrikoutPos(f, painter.device());
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "jkqtmathtext/jkqtmathtext.h"
|
||||
#include "jkqtcommon/jkqtpcodestructuring.h"
|
||||
#include "jkqtcommon/jkqtpstringtools.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
#include <cmath>
|
||||
#include <QFontMetricsF>
|
||||
#include <QDebug>
|
||||
@ -318,10 +319,10 @@ JKQTMathTextMatrixNode::LayoutInfo JKQTMathTextMatrixNode::calcLayout(QPainter &
|
||||
|
||||
JKQTMathTextEnvironment ev1=currentEv;
|
||||
|
||||
const QFontMetricsF fm(ev1.getFont(parentMathText), painter.device());
|
||||
const double strikepos=fm.strikeOutPos();
|
||||
const double xwidth=fm.boundingRect("x").width();
|
||||
const double lw=fm.lineWidth()*1.5;
|
||||
const QFont font=ev1.getFont(parentMathText);
|
||||
const double strikepos=JKQTMathTextGetFontStrikoutPos(font, painter.device());
|
||||
const double xwidth=JKQTMathTextGetBoundingRect(font,"f",painter.device()).width();
|
||||
const double lw=JKQTMathTextGetFontLineWidth(font, painter.device())*1.5;
|
||||
const double XPadding=parentMathText->getMatrixXPaddingFactor()*xwidth;
|
||||
const double YPadding=parentMathText->getMatrixYPaddingFactor()*xwidth;
|
||||
const double XSeparation=parentMathText->getMatrixXSeparationFactor()*xwidth;
|
||||
@ -372,21 +373,25 @@ JKQTMathTextNodeSize JKQTMathTextMatrixNode::getSizeInternal(QPainter& painter,
|
||||
}
|
||||
|
||||
double JKQTMathTextMatrixNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv) const {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextMatrixNode[]::draw()"));
|
||||
#endif
|
||||
|
||||
const QFontMetricsF fm(currentEv.getFont(parentMathText), painter.device());
|
||||
const QFont font=currentEv.getFont(parentMathText);
|
||||
JKQTMathTextEnvironment ev1=currentEv;
|
||||
|
||||
const LayoutInfo l=calcLayout(painter, currentEv);
|
||||
doDrawBoxes(painter, x, y, l);
|
||||
|
||||
const double xwidth=fm.boundingRect("x").width();
|
||||
const double xwidth=JKQTMathTextGetBoundingRect(font,"f",painter.device()).width();
|
||||
const double fontlw=JKQTMathTextGetFontLineWidth(font, painter.device());
|
||||
const double XSeparation=parentMathText->getMatrixXSeparationFactor()*xwidth;
|
||||
const double YSeparation=parentMathText->getMatrixYSeparationFactor()*xwidth;
|
||||
const double yTop=y-l.baselineHeight+l.topPadding;
|
||||
const double xLeft=x+l.leftPadding;
|
||||
const double linewidth=parentMathText->getMatrixLinewidthThinFactor()*fm.lineWidth();
|
||||
const double linewidthThick=parentMathText->getMatrixLinewidthHeavyFactor()*fm.lineWidth();
|
||||
const double lineSeparation=parentMathText->getMatrixLineSeparationFactor()*fm.lineWidth();
|
||||
const double linewidth=parentMathText->getMatrixLinewidthThinFactor()*fontlw;
|
||||
const double linewidthThick=parentMathText->getMatrixLinewidthHeavyFactor()*fontlw;
|
||||
const double lineSeparation=parentMathText->getMatrixLineSeparationFactor()*fontlw;
|
||||
double leftlineX=xLeft-l.leftPadding/2.0;
|
||||
double rightlineX=x+l.width-l.rightPadding/2.0;
|
||||
double toplineY=yTop-l.topPadding/2.0;
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "jkqtmathtext/jkqtmathtexttools.h"
|
||||
#include "jkqtmathtext/jkqtmathtext.h"
|
||||
#include "jkqtcommon/jkqtpstringtools.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
#include <cmath>
|
||||
#include <QFontMetricsF>
|
||||
#include <QDebug>
|
||||
@ -58,6 +59,9 @@ JKQTMathTextNodeSize JKQTMathTextModifiedTextPropsInstructionNode::getSizeIntern
|
||||
}
|
||||
|
||||
double JKQTMathTextModifiedTextPropsInstructionNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv) const {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextModifiedTextPropsInstructionNode[]::draw()"));
|
||||
#endif
|
||||
doDrawBoxes(painter, x, y, currentEv);
|
||||
JKQTMathTextEnvironment ev=currentEv;
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "jkqtmathtext/nodes/jkqtmathtextnoopnode.h"
|
||||
#include "jkqtmathtext/nodes/jkqtmathtextnode.h"
|
||||
#include "jkqtmathtext/jkqtmathtext.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
|
||||
|
||||
|
||||
@ -67,6 +68,9 @@ QString JKQTMathTextBlockNode::getTypeName() const
|
||||
|
||||
double JKQTMathTextBlockNode::draw(QPainter &painter, double x, double y, JKQTMathTextEnvironment currentEv) const
|
||||
{
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextBlockNode[]::draw()"));
|
||||
#endif
|
||||
return child->draw(painter, x, y, currentEv);
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "jkqtmathtext/jkqtmathtext.h"
|
||||
#include "jkqtcommon/jkqtpcodestructuring.h"
|
||||
#include "jkqtcommon/jkqtpstringtools.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
#include <cmath>
|
||||
#include <QFontMetricsF>
|
||||
#include <QDebug>
|
||||
@ -52,16 +53,16 @@ JKQTMathTextSqrtNode::~JKQTMathTextSqrtNode() {
|
||||
|
||||
JKQTMathTextNodeSize JKQTMathTextSqrtNode::getSizeInternal(QPainter& painter, JKQTMathTextEnvironment currentEv) const {
|
||||
JKQTMathTextNodeSize s;
|
||||
const QFontMetricsF fm(currentEv.getFont(parentMathText), painter.device());
|
||||
const QFont f=currentEv.getFont(parentMathText);
|
||||
JKQTMathTextEnvironment evSmall=currentEv;
|
||||
evSmall.fontSize=currentEv.fontSize*parentMathText->getSqrtSmallFontFactor();
|
||||
evSmall.italic=false;
|
||||
|
||||
const JKQTMathTextNodeSize cs=getChild()->getSize(painter, currentEv);
|
||||
const double descent=cs.getDescent();
|
||||
const double sqrtwidth=fm.boundingRect("X").width()*parentMathText->getSqrtWidthXFactor();
|
||||
const double newAscent=qMax(cs.baselineHeight*parentMathText->getSqrtHeightFactor(), fm.ascent());
|
||||
const double newDescent=qMax(descent*parentMathText->getSqrtHeightFactor(), fm.descent());
|
||||
const double sqrtwidth=JKQTMathTextGetBoundingRect(f, "X", painter.device()).width()*parentMathText->getSqrtWidthXFactor();
|
||||
const double newAscent=qMax(cs.baselineHeight*parentMathText->getSqrtHeightFactor(), JKQTMathTextGetFontAscent(f, painter.device()));
|
||||
const double newDescent=qMax(descent*parentMathText->getSqrtHeightFactor(), JKQTMathTextGetFontDescent(f, painter.device()));
|
||||
|
||||
s.overallHeight=newAscent+newDescent;
|
||||
s.baselineHeight=newAscent;
|
||||
@ -76,20 +77,22 @@ JKQTMathTextNodeSize JKQTMathTextSqrtNode::getSizeInternal(QPainter& painter, JK
|
||||
}
|
||||
|
||||
double JKQTMathTextSqrtNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv) const {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextSqrtNode[]::draw()"));
|
||||
#endif
|
||||
doDrawBoxes(painter, x, y, currentEv);
|
||||
|
||||
const QFont f=currentEv.getFont(parentMathText);
|
||||
const QFontMetricsF fm(f, painter.device());
|
||||
JKQTMathTextEnvironment evSmall=currentEv;
|
||||
evSmall.fontSize=currentEv.fontSize*parentMathText->getSqrtSmallFontFactor();
|
||||
evSmall.italic=false;
|
||||
|
||||
const JKQTMathTextNodeSize cs=getChild()->getSize(painter, currentEv);
|
||||
const double descent=cs.overallHeight-cs.baselineHeight;
|
||||
const double sqrtwidth=fm.boundingRect("X").width()*parentMathText->getSqrtWidthXFactor();
|
||||
const double newAscent=qMax(cs.baselineHeight*parentMathText->getSqrtHeightFactor(), fm.ascent());
|
||||
const double newDescent=qMax(descent*parentMathText->getSqrtHeightFactor(), fm.descent());
|
||||
const double linewidth=fm.lineWidth();
|
||||
const double sqrtwidth=JKQTMathTextGetBoundingRect(f, "X", painter.device()).width()*parentMathText->getSqrtWidthXFactor();
|
||||
const double newAscent=qMax(cs.baselineHeight*parentMathText->getSqrtHeightFactor(), JKQTMathTextGetFontAscent(f, painter.device()));
|
||||
const double newDescent=qMax(descent*parentMathText->getSqrtHeightFactor(), JKQTMathTextGetFontDescent(f, painter.device()));
|
||||
const double linewidth=JKQTMathTextGetFontLineWidth(f, painter.device());
|
||||
const double tinyhookSize=sqrtwidth*0.1;
|
||||
const double smalltextIndent=0.6*sqrtwidth;
|
||||
|
||||
|
@ -24,6 +24,10 @@
|
||||
#include "jkqtmathtext/jkqtmathtext.h"
|
||||
#include "jkqtcommon/jkqtpcodestructuring.h"
|
||||
#include "jkqtcommon/jkqtpstringtools.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
#include <cmath>
|
||||
#include <QFontMetricsF>
|
||||
#include <QDebug>
|
||||
@ -50,7 +54,6 @@ JKQTMathTextNodeSize JKQTMathTextSuperscriptNode::getSizeWithSpecialPlacement(QP
|
||||
JKQTMathTextEnvironment ev=currentEv;
|
||||
ev.fontSize=ev.fontSize*parentMathText->getSubsuperSizeFactor();
|
||||
const QFont fnt=currentEv.getFont(parentMathText);
|
||||
const QFontMetricsF fm(fnt, painter.device());
|
||||
//const QRectF tbr_of_letterM=JKQTMathTextGetTightBoundingRect(currentEv.getFont(parentMathText), "M", painter.device());
|
||||
const JKQTMathTextNodeSize cs=getChild()->getSize(painter, ev);
|
||||
const double childDescent=cs.getDescent();
|
||||
@ -67,7 +70,7 @@ JKQTMathTextNodeSize JKQTMathTextSuperscriptNode::getSizeWithSpecialPlacement(QP
|
||||
s.baselineHeight=s.overallHeight=cs.overallHeight+shiftToChildBottom;
|
||||
s.width=cs.width;
|
||||
if (prevNodeSizeForSpecialPlacement!=nullptr) s.strikeoutPos=prevNodeSizeForSpecialPlacement->strikeoutPos;
|
||||
else s.strikeoutPos=fm.strikeOutPos();
|
||||
else s.strikeoutPos=JKQTMathTextGetFontStrikoutPos(fnt, painter.device());
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -77,13 +80,15 @@ JKQTMathTextNodeSize JKQTMathTextSuperscriptNode::getSizeInternal(QPainter &pain
|
||||
}
|
||||
|
||||
double JKQTMathTextSuperscriptNode::drawWithSpecialPlacement(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSizeForSpecialPlacement) const {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextSuperscriptNode[]::draw()"));
|
||||
#endif
|
||||
doDrawBoxes(painter, x, y, currentEv);
|
||||
JKQTMathTextEnvironment ev=currentEv;
|
||||
ev.fontSize=ev.fontSize*parentMathText->getSubsuperSizeFactor();
|
||||
|
||||
const JKQTMathTextNodeSize cs=getChild()->getSize(painter, ev);
|
||||
const QFont fnt=currentEv.getFont(parentMathText);
|
||||
const QFontMetricsF fm(fnt, painter.device());
|
||||
const QRectF tbr=JKQTMathTextGetTightBoundingRect(fnt, "x", painter.device());
|
||||
const double xh=tbr.height();
|
||||
//qDebug()<<"x="<<x<<" prevNodeSizeForSpecialPlacement="<<prevNodeSizeForSpecialPlacement<<" font="<<currentEv.getFont(parentMathText);
|
||||
@ -98,11 +103,14 @@ double JKQTMathTextSuperscriptNode::drawWithSpecialPlacement(QPainter& painter,
|
||||
|
||||
double xx=x;
|
||||
|
||||
return getChild()->draw(painter, xx, y-(shiftToChildBottom+childDescent), ev);//+0.5*fm.boundingRect("A").width();
|
||||
return getChild()->draw(painter, xx, y-(shiftToChildBottom+childDescent), ev);
|
||||
}
|
||||
|
||||
double JKQTMathTextSuperscriptNode::draw(QPainter &painter, double x, double y, JKQTMathTextEnvironment currentEv) const
|
||||
{
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextSuperscriptNode[]::draw()"));
|
||||
#endif
|
||||
return drawWithSpecialPlacement(painter, x, y, currentEv, nullptr);
|
||||
}
|
||||
|
||||
@ -141,7 +149,6 @@ JKQTMathTextNodeSize JKQTMathTextSubscriptNode::getSizeWithSpecialPlacement(QPai
|
||||
JKQTMathTextEnvironment ev=currentEv;
|
||||
ev.fontSize=ev.fontSize*parentMathText->getSubsuperSizeFactor();
|
||||
const QFont f(ev.getFont(parentMathText));
|
||||
const QFontMetricsF fm(f, painter.device());
|
||||
//const QRectF tbr_of_letterM=JKQTMathTextGetTightBoundingRect(currentEv.getFont(parentMathText), "M", painter.device());
|
||||
|
||||
const JKQTMathTextNodeSize cs=getChild()->getSize(painter, ev);
|
||||
@ -159,7 +166,7 @@ JKQTMathTextNodeSize JKQTMathTextSubscriptNode::getSizeWithSpecialPlacement(QPai
|
||||
s.baselineHeight=cs.baselineHeight-shift_to_childBaseline;
|
||||
s.overallHeight=cs.overallHeight;
|
||||
if (prevNodeSizeForSpecialPlacement!=nullptr) s.strikeoutPos=prevNodeSizeForSpecialPlacement->strikeoutPos;
|
||||
else s.strikeoutPos=fm.strikeOutPos();
|
||||
else s.strikeoutPos=JKQTMathTextGetFontStrikoutPos(f, painter.device());
|
||||
s.width=cs.width;
|
||||
return s;
|
||||
}
|
||||
@ -170,11 +177,13 @@ JKQTMathTextNodeSize JKQTMathTextSubscriptNode::getSizeInternal(QPainter &painte
|
||||
}
|
||||
|
||||
double JKQTMathTextSubscriptNode::drawWithSpecialPlacement(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv, const JKQTMathTextNodeSize* prevNodeSizeForSpecialPlacement) const {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextSubscriptNode[]::draw()"));
|
||||
#endif
|
||||
doDrawBoxes(painter, x, y, currentEv);
|
||||
JKQTMathTextEnvironment ev=currentEv;
|
||||
ev.fontSize=ev.fontSize*parentMathText->getSubsuperSizeFactor();
|
||||
QFont f=ev.getFont(parentMathText);
|
||||
const QFontMetricsF fm(f, painter.device());
|
||||
//const QRectF tbr_of_letterM=JKQTMathTextGetTightBoundingRect(currentEv.getFont(parentMathText), "M", painter.device());
|
||||
|
||||
const JKQTMathTextNodeSize cs=getChild()->getSize(painter, ev);
|
||||
@ -191,11 +200,14 @@ double JKQTMathTextSubscriptNode::drawWithSpecialPlacement(QPainter& painter, do
|
||||
//qDebug()<<"baselineHeight="<<baselineHeight<<", overallHeight="<<overallHeight<<", strikeoutPos="<<strikeoutPos;
|
||||
//qDebug()<<"shift="<<shift<<", yshift="<<yshift;
|
||||
double xx=x;
|
||||
return getChild()->draw(painter, xx, y+shift_to_childBaseline, ev);//+0.5*fm.boundingRect("A").width();
|
||||
return getChild()->draw(painter, xx, y+shift_to_childBaseline, ev);
|
||||
}
|
||||
|
||||
double JKQTMathTextSubscriptNode::draw(QPainter &painter, double x, double y, JKQTMathTextEnvironment currentEv) const
|
||||
{
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextSubscriptNode[]::draw()"));
|
||||
#endif
|
||||
return drawWithSpecialPlacement(painter, x, y, currentEv, nullptr);
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "jkqtmathtext/jkqtmathtext.h"
|
||||
#include "jkqtcommon/jkqtpcodestructuring.h"
|
||||
#include "jkqtcommon/jkqtpstringtools.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
#include <cmath>
|
||||
#include <QFontMetricsF>
|
||||
#include <QDebug>
|
||||
@ -54,14 +55,17 @@ JKQTMathTextNodeSize JKQTMathTextSymbolNode::getSizeInternal(QPainter& painter,
|
||||
return getSymbolSize(painter, currentEv);
|
||||
}
|
||||
|
||||
QRectF JKQTMathTextSymbolNode::getBoundingRect(const QFontMetricsF &fm, const QString &text, GlobalSymbolFlags globalFlags)
|
||||
QRectF JKQTMathTextSymbolNode::getBoundingRect(const QFont &f, const QString &text, GlobalSymbolFlags globalFlags, QPaintDevice *pd)
|
||||
{
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextSymbolNode[]::getBoundingRect()"));
|
||||
#endif
|
||||
if (has(globalFlags, MakeWhitespaceHalf) && text.contains(' ')) {
|
||||
const QStringList str=text.simplified().trimmed().split(' ');
|
||||
const QRectF brSp=fm.boundingRect("i");
|
||||
const QRectF brSp=JKQTMathTextGetBoundingRect(f,"i",pd);
|
||||
QRectF br;
|
||||
for (int i=0; i<str.size(); i++) {
|
||||
const QRectF lbr=fm.boundingRect(str[i]);
|
||||
const QRectF lbr=JKQTMathTextGetBoundingRect(f,str[i],pd);
|
||||
if (i==0) br=lbr;
|
||||
else {
|
||||
br.setWidth(br.width()+brSp.width()/2.0+lbr.width());
|
||||
@ -75,18 +79,21 @@ QRectF JKQTMathTextSymbolNode::getBoundingRect(const QFontMetricsF &fm, const QS
|
||||
}
|
||||
return br;
|
||||
} else {
|
||||
return fm.boundingRect(text);
|
||||
return JKQTMathTextGetBoundingRect(f,text,pd);
|
||||
}
|
||||
}
|
||||
|
||||
QRectF JKQTMathTextSymbolNode::getTightBoundingRect(const QFontMetricsF &fm, const QString &text, GlobalSymbolFlags globalFlags)
|
||||
QRectF JKQTMathTextSymbolNode::getTightBoundingRect(const QFont &f, const QString &text, GlobalSymbolFlags globalFlags, QPaintDevice* pd)
|
||||
{
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextSymbolNode[]::getTightBoundingRect()"));
|
||||
#endif
|
||||
if (has(globalFlags, MakeWhitespaceHalf) && text.contains(' ')) {
|
||||
const QStringList str=text.simplified().trimmed().split(' ');
|
||||
const QRectF brSp=fm.boundingRect("i");
|
||||
const QRectF brSp=JKQTMathTextGetBoundingRect(f,"i",pd);
|
||||
QRectF br;
|
||||
for (int i=0; i<str.size(); i++) {
|
||||
const QRectF lbr=fm.tightBoundingRect(str[i]);
|
||||
const QRectF lbr=JKQTMathTextGetTightBoundingRect(f,str[i],pd);
|
||||
if (i==0) br=lbr;
|
||||
else {
|
||||
br.setWidth(br.width()+brSp.width()/2.0+lbr.width());
|
||||
@ -100,23 +107,25 @@ QRectF JKQTMathTextSymbolNode::getTightBoundingRect(const QFontMetricsF &fm, con
|
||||
}
|
||||
return br;
|
||||
} else {
|
||||
return fm.tightBoundingRect(text);
|
||||
return JKQTMathTextGetTightBoundingRect(f,text,pd);
|
||||
}
|
||||
}
|
||||
|
||||
void JKQTMathTextSymbolNode::drawText(QPainter &p, const QString &text, GlobalSymbolFlags globalFlags, SymbolFlags symflags)
|
||||
{
|
||||
const QFontMetricsF fm(p.font(), p.device());
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextSymbolNode[]::drawText()"));
|
||||
#endif
|
||||
if (has(globalFlags, MakeWhitespaceHalf) && text.contains(' ')) {
|
||||
const QStringList str=text.simplified().trimmed().split(' ');
|
||||
const QRectF brSp=fm.boundingRect("i");
|
||||
const QRectF brSp=JKQTMathTextGetBoundingRect(p.font(), "i", p.device());
|
||||
double x=0;
|
||||
for (int i=0; i<str.size(); i++) {
|
||||
p.drawText(QPointF(x,0), str[i]);
|
||||
x=x+fm.boundingRect(str[i]).width()+brSp.width()/2.0;
|
||||
x=x+JKQTMathTextGetBoundingRect(p.font(), str[i], p.device()).width()+brSp.width()/2.0;
|
||||
}
|
||||
} else {
|
||||
const QRectF tbr=fm.tightBoundingRect(text);
|
||||
const QRectF tbr=JKQTMathTextGetBoundingRect(p.font(), text, p.device());
|
||||
p.save(); auto __finalpaint=JKQTPFinally([&p]() {p.restore();});
|
||||
p.translate(tbr.center());
|
||||
if (has(symflags, RotateSymbol90)) {
|
||||
@ -138,6 +147,9 @@ void JKQTMathTextSymbolNode::drawText(QPainter &p, const QString &text, GlobalSy
|
||||
|
||||
|
||||
double JKQTMathTextSymbolNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv) const {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextSymbolNode[]::draw()"));
|
||||
#endif
|
||||
const NodeSize s=getSymbolSize(painter, currentEv);
|
||||
doDrawBoxes(painter, x, y, s);
|
||||
|
||||
@ -146,20 +158,18 @@ double JKQTMathTextSymbolNode::draw(QPainter& painter, double x, double y, JKQTM
|
||||
const auto drawProps=fullProps.getDrawingData(currentEv, parentMathText, painter);
|
||||
const QFont f=drawProps.first;
|
||||
const QFont fnonItalic=JKQTMathTextGetNonItalic(drawProps.first);
|
||||
const QFontMetricsF fm(f, painter.device());
|
||||
const QFontMetricsF fmNonItalic(fnonItalic, painter.device());
|
||||
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 tbrNonItalic=getTightBoundingRect(fmNonItalic, sym, globalFlags);
|
||||
const QRectF tbr=getTightBoundingRect(f, sym, globalFlags, painter.device());
|
||||
const QRectF tbrNonItalic=getTightBoundingRect(fnonItalic, sym, globalFlags, painter.device());
|
||||
//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=(s.width-tbr.width())/2.0;
|
||||
const QPointF x0(x+xShift-tbr.x(), y+yShift);
|
||||
double italic_xcorrection=fabs(tbr.width()-tbrNonItalic.width());
|
||||
if (fabs(italic_xcorrection)<1e-6) italic_xcorrection=double(fm.boundingRect(' ').width())*0.4;
|
||||
if (fabs(italic_xcorrection)<1e-6) italic_xcorrection=double(JKQTMathTextGetBoundingRect(f, " ", painter.device()).width())*0.4;
|
||||
|
||||
//std::cout<<"SYMB::draw(): symbolName="<<symbolName.toStdString()<<" font="<<f.family().toStdString()<<" sym="<<sym.toStdString()<<"(0x"<<std::hex<<((sym.size()==0)?uint64_t(0):uint64_t(sym[0].unicode()))<<") yShiftFactor="<<symprops.yShiftFactor<<"\n";
|
||||
|
||||
@ -173,7 +183,7 @@ double JKQTMathTextSymbolNode::draw(QPainter& painter, double x, double y, JKQTM
|
||||
if (has(symflags, DrawLeftHBar) || has (symflags, DrawRightHBar)) {
|
||||
//qDebug()<<" -> DrawLeftHBar or DrawRightHBar";
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
painter.setPen(QPen(currentEv.color, fm.lineWidth()));
|
||||
painter.setPen(QPen(currentEv.color, JKQTMathTextGetFontLineWidth(f, painter.device())));
|
||||
const double xh=JKQTMathTextGetTightBoundingRect(f, "x", painter.device()).height();
|
||||
const double ybar=-xh*1.1;
|
||||
const double deltaybar=xh*0.2;
|
||||
@ -184,7 +194,7 @@ double JKQTMathTextSymbolNode::draw(QPainter& painter, double x, double y, JKQTM
|
||||
if (has(symflags, DrawVertLine)) {
|
||||
//qDebug()<<" -> DrawVertLine";
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
painter.setPen(QPen(currentEv.color, fm.lineWidth()));
|
||||
painter.setPen(QPen(currentEv.color, JKQTMathTextGetFontLineWidth(f, painter.device())));
|
||||
const double ybar=tbr.top();
|
||||
const double xbarstart=italic_xcorrection+tbrNonItalic.width()/2.0;
|
||||
const double xbarend=tbrNonItalic.width()/2.0;
|
||||
@ -192,22 +202,16 @@ double JKQTMathTextSymbolNode::draw(QPainter& painter, double x, double y, JKQTM
|
||||
}
|
||||
if (has(symflags, DrawSlash)) {
|
||||
//qDebug()<<" -> DrawSlash";
|
||||
painter.drawText(QPointF((s.width-fm.boundingRect('/').width())/2.0,0),"/");
|
||||
painter.drawText(QPointF((s.width-JKQTMathTextGetBoundingRect(f, "/", painter.device()).width())/2.0,0),"/");
|
||||
}
|
||||
if (has(symflags, DrawBackSlash)) {
|
||||
//qDebug()<<" -> DrawBackSlash";
|
||||
painter.drawText(QPointF((s.width-fm.boundingRect('\\').width())/2.0,0),"\\");
|
||||
painter.drawText(QPointF((s.width-JKQTMathTextGetBoundingRect(f, "\\", painter.device()).width())/2.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
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
painter.setPen(QPen(currentEv.color, fm.lineWidth()));
|
||||
painter.setPen(QPen(currentEv.color, JKQTMathTextGetFontLineWidth(f, painter.device())));
|
||||
painter.drawRect(QRectF(x0.x(), x0.y()-tbrNoSymbol.height(), tbrNoSymbol.width(), tbrNoSymbol.height()));
|
||||
}
|
||||
|
||||
@ -232,18 +236,20 @@ QString JKQTMathTextSymbolNode::getSymbolName() const {
|
||||
|
||||
JKQTMathTextSymbolNode::NodeSize JKQTMathTextSymbolNode::getSymbolSize(QPainter &painter, JKQTMathTextEnvironment currentEv) const
|
||||
{
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextSymbolNode[]::getSymbolSize()"));
|
||||
#endif
|
||||
NodeSize s;
|
||||
|
||||
const auto fullProps=symbols().value(symbolName, SymbolFullProps());
|
||||
const GlobalSymbolFlags globalFlags=fullProps.globalFlags;
|
||||
const auto drawProps=fullProps.getDrawingData(currentEv, parentMathText, painter);
|
||||
const QFont f=drawProps.first;
|
||||
const QFontMetricsF fm(f, painter.device());
|
||||
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 tbr=getTightBoundingRect(f, sym, globalFlags, painter.device());
|
||||
const QRectF br=getBoundingRect(f, sym, globalFlags, painter.device());
|
||||
const QRectF tbrNoSymbol=JKQTMathTextGetTightBoundingRect(f, "X", painter.device());
|
||||
const QRectF mintbr=JKQTMathTextGetTightBoundingRect(f, "(", painter.device());
|
||||
const QRectF dottbr=JKQTMathTextGetTightBoundingRect(f, ".", painter.device());
|
||||
@ -272,13 +278,13 @@ JKQTMathTextSymbolNode::NodeSize JKQTMathTextSymbolNode::getSymbolSize(QPainter
|
||||
const double oldDescent=s.overallHeight-s.baselineHeight;
|
||||
|
||||
if (has(symflags, HeightIsAscent)) {
|
||||
s.baselineHeight=fm.ascent();
|
||||
s.baselineHeight=JKQTMathTextGetFontAscent(f, painter.device());
|
||||
s.overallHeight=s.baselineHeight+oldDescent;
|
||||
}
|
||||
if (has(symflags, RotateSymbol90)) {
|
||||
s.width=qMax(s.overallHeight, s.width);
|
||||
}
|
||||
s.strikeoutPos=fm.strikeOutPos();
|
||||
s.strikeoutPos=JKQTMathTextGetFontStrikoutPos(f, painter.device());
|
||||
|
||||
if (has(globalFlags, IntLikeSymbolCorrection)) {
|
||||
if (has(globalFlags, SubSuperscriptBelowAboveSymbol)) {
|
||||
@ -288,7 +294,7 @@ JKQTMathTextSymbolNode::NodeSize JKQTMathTextSymbolNode::getSymbolSize(QPainter
|
||||
s.topXCorrection=dottbr.width();
|
||||
}
|
||||
if (has(globalFlags, SubscriptCorrection) && sym.size()>0) {
|
||||
s.baselineXCorrection=fm.rightBearing(sym[sym.size()-1]);
|
||||
s.baselineXCorrection=JKQTMathTextGetRightBearing(f,sym[sym.size()-1],painter.device());
|
||||
}
|
||||
|
||||
return s;
|
||||
@ -384,7 +390,7 @@ const QHash<QString, JKQTMathTextSymbolNode::SymbolFullProps> &JKQTMathTextSymbo
|
||||
* STANDARD Symbols available in all standard fonts
|
||||
**************************************************************************************/
|
||||
symbols["#"]=SimpleTextSymbol("#", "#");
|
||||
symbols["%"]=SimpleTextSymbol("%", "≫");
|
||||
symbols["%"]=SimpleTextSymbol("%", "&percent;");
|
||||
symbols["&"]=SimpleTextSymbol("&", "&");
|
||||
symbols["("]=SimpleUprightTextSymbol("(");
|
||||
symbols[")"]=SimpleUprightTextSymbol(")");
|
||||
|
@ -156,9 +156,9 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathTextSymbolNode: public JKQTMathTextNode {
|
||||
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);
|
||||
static QRectF getBoundingRect(const QFont &fm, const QString& text, GlobalSymbolFlags globalFlags, QPaintDevice *pd);
|
||||
/** \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);
|
||||
static QRectF getTightBoundingRect(const QFont& fm, const QString& text, GlobalSymbolFlags globalFlags, QPaintDevice *pd);
|
||||
/** \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, SymbolFlags symflags);
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "jkqtmathtext/jkqtmathtext.h"
|
||||
#include "jkqtcommon/jkqtpcodestructuring.h"
|
||||
#include "jkqtcommon/jkqtpstringtools.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
#include <cmath>
|
||||
#include <QFontMetricsF>
|
||||
#include <QDebug>
|
||||
@ -141,15 +142,7 @@ JKQTMathTextTextNode::LayoutInfo JKQTMathTextTextNode::calcLayout(QPainter &pain
|
||||
const QFont fUpright=JKQTMathTextGetNonItalic(f);
|
||||
const QFont fFallbackSym=currentEv.exchangedFontFor(MTEFallbackSymbols).getFont(parentMathText);
|
||||
const QFont fRoman=currentEv.exchangedFontForRoman().getFont(parentMathText);
|
||||
const QFontMetricsF fmUpright(fUpright, painter.device());
|
||||
const QFontMetricsF fm(f, painter.device());
|
||||
const QFontMetricsF fmFallbackSym(fFallbackSym, painter.device());
|
||||
const QFontMetricsF fmRoman(fRoman, painter.device());
|
||||
#if (QT_VERSION>=QT_VERSION_CHECK(5, 15, 0))
|
||||
const double sp=fm.horizontalAdvance(' ');
|
||||
#else
|
||||
const double sp=fm.width(' ');
|
||||
#endif
|
||||
const double sp=JKQTMathTextGetHorAdvance(f, " ", painter.device());
|
||||
l.width=0;
|
||||
double ascent=0;
|
||||
double descent=0;
|
||||
@ -160,23 +153,23 @@ JKQTMathTextTextNode::LayoutInfo JKQTMathTextTextNode::calcLayout(QPainter &pain
|
||||
switch(l.fontMode[i]) {
|
||||
case FMasDefined:
|
||||
case FMasDefinedOutline:
|
||||
br=fm.boundingRect(l.textpart[i]);
|
||||
br=JKQTMathTextGetBoundingRect(f, l.textpart[i], painter.device());
|
||||
tbr=JKQTMathTextGetTightBoundingRect(f, l.textpart[i], painter.device());
|
||||
if (f.italic() && l.textpart[i].size()>0) l.baselineXCorrection=fm.rightBearing(l.textpart[i].operator[](l.textpart[i].size()-1));
|
||||
if (f.italic() && l.textpart[i].size()>0) l.baselineXCorrection=JKQTMathTextGetRightBearing(f,l.textpart[i].operator[](l.textpart[i].size()-1),painter.device());
|
||||
break;
|
||||
case FMasDefinedForceUpright:
|
||||
br=fmUpright.boundingRect(l.textpart[i]);
|
||||
br=JKQTMathTextGetBoundingRect(fUpright, l.textpart[i], painter.device());
|
||||
tbr=JKQTMathTextGetTightBoundingRect(fUpright, l.textpart[i], painter.device());
|
||||
break;
|
||||
case FMroman:
|
||||
br=fmRoman.boundingRect(l.textpart[i]);
|
||||
br=JKQTMathTextGetBoundingRect(fRoman, l.textpart[i], painter.device());
|
||||
tbr=JKQTMathTextGetTightBoundingRect(fRoman, l.textpart[i], painter.device());
|
||||
if (fRoman.italic() && l.textpart[i].size()>0) l.baselineXCorrection=fmRoman.rightBearing(l.textpart[i].operator[](l.textpart[i].size()-1));
|
||||
if (fRoman.italic() && l.textpart[i].size()>0) l.baselineXCorrection=JKQTMathTextGetRightBearing(fRoman,l.textpart[i].operator[](l.textpart[i].size()-1),painter.device());
|
||||
break;
|
||||
case FMfallbackSymbol:
|
||||
br=fmFallbackSym.boundingRect(l.textpart[i]);
|
||||
br=JKQTMathTextGetBoundingRect(fFallbackSym, l.textpart[i], painter.device());
|
||||
tbr=JKQTMathTextGetTightBoundingRect(fFallbackSym, l.textpart[i], painter.device());
|
||||
if (fFallbackSym.italic() && l.textpart[i].size()>0) l.baselineXCorrection=fmFallbackSym.rightBearing(l.textpart[i].operator[](l.textpart[i].size()-1));
|
||||
if (fFallbackSym.italic() && l.textpart[i].size()>0) l.baselineXCorrection=JKQTMathTextGetRightBearing(fFallbackSym,l.textpart[i].operator[](l.textpart[i].size()-1),painter.device());
|
||||
break;
|
||||
}
|
||||
l.textpartXPos.append(l.width);
|
||||
@ -193,7 +186,7 @@ JKQTMathTextTextNode::LayoutInfo JKQTMathTextTextNode::calcLayout(QPainter &pain
|
||||
}
|
||||
l.overallHeight=(ascent+descent); //fm.height();
|
||||
l.baselineHeight=ascent;
|
||||
l.strikeoutPos=fm.strikeOutPos();
|
||||
l.strikeoutPos=JKQTMathTextGetFontStrikoutPos(f, painter.device());
|
||||
return l;
|
||||
}
|
||||
|
||||
@ -285,6 +278,9 @@ void JKQTMathTextTextNode::splitTextForLayout(QPainter &painter, JKQTMathTextEnv
|
||||
}
|
||||
|
||||
double JKQTMathTextTextNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv) const {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextTextNode[]::draw()"));
|
||||
#endif
|
||||
const LayoutInfo l=calcLayout(painter, currentEv);
|
||||
doDrawBoxes(painter, x, y, l);
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "jkqtmathtext/jkqtmathtext.h"
|
||||
#include "jkqtcommon/jkqtpcodestructuring.h"
|
||||
#include "jkqtcommon/jkqtpstringtools.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
#include <cmath>
|
||||
#include <QFontMetricsF>
|
||||
#include <QDebug>
|
||||
@ -81,6 +82,9 @@ size_t JKQTMathTextVerbatimNode::getTabSize() const
|
||||
|
||||
double JKQTMathTextVerbatimNode::draw(QPainter &painter, double x, double y, JKQTMathTextEnvironment currentEv) const
|
||||
{
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextVerbatimNode[]::draw()"));
|
||||
#endif
|
||||
transformEnvironment(currentEv);
|
||||
const LayoutInfo l=calcLayout(painter, currentEv);
|
||||
doDrawBoxes(painter, x, y, l);
|
||||
@ -134,10 +138,10 @@ JKQTMathTextVerbatimNode::LayoutInfo JKQTMathTextVerbatimNode::calcLayout(QPaint
|
||||
QFont f=currentEv.getFont(parentMathText);
|
||||
f.setStyleStrategy(QFont::PreferDefault);
|
||||
f.setFixedPitch(true);
|
||||
const QFontMetricsF fm(f, painter.device());
|
||||
const double linespacing=fm.lineSpacing()*lineSpacingFactor;
|
||||
const double fleading=fm.leading();
|
||||
const double synLeading=fm.lineWidth();
|
||||
const qreal fascent=JKQTMathTextGetFontAscent(f, painter.device());
|
||||
const double linespacing=JKQTMathTextGetFontLineSpacing(f, painter.device())*lineSpacingFactor;
|
||||
const double fleading=JKQTMathTextGetFontLeading(f, painter.device());
|
||||
const double synLeading=JKQTMathTextGetFontLineWidth(f, painter.device());
|
||||
const double lineLeading=((fabs(fleading)>1e-6)?fleading:synLeading)*lineSpacingFactor;
|
||||
|
||||
if (text.size()<=0) {
|
||||
@ -154,18 +158,18 @@ JKQTMathTextVerbatimNode::LayoutInfo JKQTMathTextVerbatimNode::calcLayout(QPaint
|
||||
for (int i=0; i<l.lines.size(); i++) {
|
||||
|
||||
if (i==0) {
|
||||
heightSum=fm.ascent();
|
||||
heightSum=fascent;
|
||||
} else if (i>0) {
|
||||
const double deltaLine=qMax(linespacing, descents.last()+lineLeading+fm.ascent());
|
||||
const double deltaLine=qMax(linespacing, descents.last()+lineLeading+fascent);
|
||||
heightSum=heightSum+deltaLine;
|
||||
y=y+deltaLine;
|
||||
}
|
||||
widths<<fm.boundingRect(l.lines[i]).width();
|
||||
widths<<JKQTMathTextGetBoundingRect(f,l.lines[i],painter.device()).width();
|
||||
l.width=qMax(l.width, widths.last());
|
||||
heights<<fm.height();
|
||||
ascents<<fm.ascent();
|
||||
descents<<fm.descent();
|
||||
strikeouts<<fm.strikeOutPos();
|
||||
heights<<JKQTMathTextGetFontHeight(f, painter.device());
|
||||
ascents<<fascent;
|
||||
descents<<JKQTMathTextGetFontDescent(f, painter.device());
|
||||
strikeouts<<JKQTMathTextGetFontStrikoutPos(f, painter.device());
|
||||
ysFromFirstLine<<y;
|
||||
}
|
||||
heightSum+=descents.last();
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "jkqtmathtext/jkqtmathtext.h"
|
||||
#include "jkqtcommon/jkqtpcodestructuring.h"
|
||||
#include "jkqtcommon/jkqtpstringtools.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
#include <cmath>
|
||||
#include <QFontMetricsF>
|
||||
#include <QDebug>
|
||||
@ -76,10 +77,10 @@ JKQTMathTextVerticalListNode::LayoutInfo JKQTMathTextVerticalListNode::calcLayou
|
||||
QList<double> ysFromFirstLine; // y-position of each line, where the first line is always at y=0 (i.e. ysFromFirstLine[0]==0)
|
||||
double y=0;
|
||||
for (int i=0; i<nodes.size(); i++) {
|
||||
const QFontMetricsF fm(currentEv.getFont(parentMathText), painter.device());
|
||||
const double linespacing=fm.lineSpacing()*lineSpacingFactor;
|
||||
const double fleading=fm.leading();
|
||||
const double synLeading=fm.lineWidth();
|
||||
const QFont f=currentEv.getFont(parentMathText);
|
||||
const double linespacing=JKQTMathTextGetFontLineSpacing(f, painter.device())*lineSpacingFactor;
|
||||
const double fleading=JKQTMathTextGetFontLeading(f, painter.device());
|
||||
const double synLeading=JKQTMathTextGetFontLineWidth(f, painter.device());
|
||||
const double lineLeading=((fabs(fleading)>1e-6)?fleading:synLeading)*lineSpacingFactor;
|
||||
|
||||
const JKQTMathTextNodeSize loc=nodes[i]->getSize(painter, currentEv);
|
||||
@ -145,6 +146,9 @@ JKQTMathTextVerticalListNode::LayoutInfo JKQTMathTextVerticalListNode::calcLayou
|
||||
}
|
||||
|
||||
double JKQTMathTextVerticalListNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment ev) const {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextVerticalListNode[]::draw()"));
|
||||
#endif
|
||||
JKQTMathTextEnvironment currentEv=ev;
|
||||
doDrawBoxes(painter, x, y, currentEv);
|
||||
const LayoutInfo l=calcLayout(painter, currentEv);
|
||||
|
@ -25,6 +25,9 @@
|
||||
#include "jkqtmathtext/jkqtmathtext.h"
|
||||
#include "jkqtcommon/jkqtpcodestructuring.h"
|
||||
#include "jkqtcommon/jkqtpstringtools.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
#include "jkqtcommon/jkqtpdebuggingtools.h"
|
||||
#include <cmath>
|
||||
#include <QFontMetricsF>
|
||||
#include <QDebug>
|
||||
@ -114,6 +117,9 @@ size_t JKQTMathTextWhitespaceNode::getWhitespaceCount() const
|
||||
|
||||
double JKQTMathTextWhitespaceNode::draw(QPainter &painter, double x, double y, JKQTMathTextEnvironment currentEv) const
|
||||
{
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextWhitespaceNode[]::draw()"));
|
||||
#endif
|
||||
const JKQTMathTextNodeSize s=getSize(painter, currentEv);
|
||||
doDrawBoxes(painter, x,y,s);
|
||||
return x+s.width;
|
||||
@ -123,11 +129,10 @@ JKQTMathTextNodeSize JKQTMathTextWhitespaceNode::getSizeInternal(QPainter &paint
|
||||
{
|
||||
JKQTMathTextNodeSize s;
|
||||
const double singelWidthPIX=Type2PixelWidth(whitespace.type, currentEv, painter.device());
|
||||
const QFontMetricsF fm(currentEv.getFont(parentMathText), painter.device());
|
||||
s.width=singelWidthPIX*static_cast<double>(whitespace.count);
|
||||
s.baselineHeight=0;
|
||||
s.overallHeight=0;
|
||||
s.strikeoutPos=fm.strikeOutPos();
|
||||
s.strikeoutPos=JKQTMathTextGetFontStrikoutPos(currentEv.getFont(parentMathText), painter.device());
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -179,14 +184,9 @@ QString JKQTMathTextWhitespaceNode::Type2String(Types type)
|
||||
|
||||
double JKQTMathTextWhitespaceNode::Type2PixelWidth(Types type, JKQTMathTextEnvironment currentEv, QPaintDevice* pd) const
|
||||
{
|
||||
const QFontMetricsF fm(currentEv.getFont(parentMathText), pd);
|
||||
#if (QT_VERSION>=QT_VERSION_CHECK(5, 15, 0))
|
||||
const double em=fm.horizontalAdvance(QChar(0x2003));//currentEv.fontSize;
|
||||
const double sp=fm.horizontalAdvance(' ');//currentEv.fontSize;
|
||||
#else
|
||||
const double em=fm.width(QChar(0x2003));//currentEv.fontSize;
|
||||
const double sp=fm.width(' ');//currentEv.fontSize;
|
||||
#endif
|
||||
const QFont f=currentEv.getFont(parentMathText);
|
||||
const double sp=JKQTMathTextGetHorAdvance(f, " ", pd);
|
||||
const double em=JKQTMathTextGetHorAdvance(f, QChar(0x2003), pd);
|
||||
const double en=em/2.0;
|
||||
switch (type) {
|
||||
case WSTNormal: return sp;
|
||||
@ -255,13 +255,8 @@ double JKQTMathTextEmptyBoxNode::Units2PixelWidth(double value, Units unit, JKQT
|
||||
{
|
||||
QFont f=currentEv.getFont(parentMathText);
|
||||
f.setStyleStrategy(QFont::PreferDefault);
|
||||
const QFontMetricsF fm(f, pd);
|
||||
if (unit==EBUem) {
|
||||
#if (QT_VERSION>=QT_VERSION_CHECK(5, 15, 0))
|
||||
const double em=fm.horizontalAdvance(QChar(0x2003));//currentEv.fontSize;
|
||||
#else
|
||||
const double em=fm.width(QChar(0x2003));//currentEv.fontSize;
|
||||
#endif
|
||||
const double em=JKQTMathTextGetHorAdvance(f, QChar(0x2003), pd);
|
||||
//qDebug()<<"em="<<em<<"pix";
|
||||
return value*em;
|
||||
} else if (unit==EBUex) {
|
||||
@ -319,6 +314,9 @@ double JKQTMathTextEmptyBoxNode::getHeight() const
|
||||
|
||||
double JKQTMathTextEmptyBoxNode::draw(QPainter &painter, double x, double y, JKQTMathTextEnvironment currentEv) const
|
||||
{
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextEmptyBoxNode[]::draw()"));
|
||||
#endif
|
||||
const auto s=getSize(painter, currentEv);
|
||||
doDrawBoxes(painter, x,y,s);
|
||||
return x+s.width;
|
||||
@ -327,7 +325,6 @@ double JKQTMathTextEmptyBoxNode::draw(QPainter &painter, double x, double y, JKQ
|
||||
JKQTMathTextNodeSize JKQTMathTextEmptyBoxNode::getSizeInternal(QPainter &painter, JKQTMathTextEnvironment currentEv) const
|
||||
{
|
||||
JKQTMathTextNodeSize s;
|
||||
const QFontMetricsF fm(currentEv.getFont(parentMathText), painter.device());
|
||||
s.width=Units2PixelWidth(width, widthUnit, currentEv, painter.device());
|
||||
s.overallHeight=Units2PixelWidth(height, heightUnit, currentEv, painter.device());
|
||||
if (height>0) {
|
||||
@ -335,7 +332,7 @@ JKQTMathTextNodeSize JKQTMathTextEmptyBoxNode::getSizeInternal(QPainter &painter
|
||||
} else {
|
||||
s.baselineHeight=0;
|
||||
}
|
||||
s.strikeoutPos=fm.strikeOutPos();
|
||||
s.strikeoutPos=JKQTMathTextGetFontStrikoutPos(currentEv.getFont(parentMathText), painter.device());
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -400,6 +397,9 @@ JKQTMathTextNodeSize JKQTMathTextPhantomNode::getSizeInternal(QPainter& painter,
|
||||
}
|
||||
|
||||
double JKQTMathTextPhantomNode::draw(QPainter& painter, double x, double y, JKQTMathTextEnvironment currentEv) const {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTMathTextPhantomNode[]::draw()"));
|
||||
#endif
|
||||
const JKQTMathTextNodeSize s=getSize(painter, currentEv);
|
||||
doDrawBoxes(painter, x, y, s);
|
||||
return x+s.width;
|
||||
|
@ -63,13 +63,15 @@ void JKQTPBaseKey::saveSettings(QSettings& settings, const QString& group) const
|
||||
|
||||
void JKQTPBaseKey::drawKey(JKQTPEnhancedPainter &painter, const QRectF &rect, const KeySizeDescription& layout)
|
||||
{
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTPBaseKey[%1]::drawKey()").arg(objectName()));
|
||||
#endif
|
||||
if (!keyStyle().visible) return;
|
||||
|
||||
QFont kf(JKQTMathTextFontSpecifier::fromFontSpec(keyStyle().fontName).fontName(), keyStyle().fontSize);
|
||||
kf.setPointSizeF(keyStyle().fontSize*getParent()->getFontSizeMultiplier());
|
||||
const QFontMetricsF kfm(kf, painter.device());
|
||||
const qreal Xwid=kfm.boundingRect('X').width();
|
||||
const qreal FHeight=kfm.height();
|
||||
const qreal Xwid=JKQTMathTextGetBoundingRect(kf,"X",painter.device()).width();
|
||||
const qreal FHeight=JKQTMathTextGetFontHeight(kf, painter.device());
|
||||
|
||||
// determine layouting info and size
|
||||
QPointF internalOffset(0,0);
|
||||
@ -130,6 +132,7 @@ void JKQTPBaseKey::drawKey(JKQTPEnhancedPainter &painter, const QRectF &rect, co
|
||||
// draw key table/contents
|
||||
x0=x0+internalOffset;
|
||||
QPointF xi=x0;
|
||||
int ic=0;
|
||||
for (const auto& c: layout.d->columns) {
|
||||
xi.setY(x0.y());
|
||||
int ir=0;
|
||||
@ -137,12 +140,22 @@ void JKQTPBaseKey::drawKey(JKQTPEnhancedPainter &painter, const QRectF &rect, co
|
||||
const QRectF sampleRect(xi, QSizeF(keyStyle().sampleLineLength*Xwid, keyStyle().sampleHeight*FHeight));
|
||||
const double rowHeight=layout.d->calcRowHeight(ir, sampleRect.height());
|
||||
const QRectF textRect(xi+QPointF((keyStyle().sampleLineLength+keyStyle().xSeparation)*Xwid, 0), QSize(r.size.width(), rowHeight));
|
||||
drawEntrySample(r.id, painter, sampleRect),
|
||||
getParentMathText()->setFontColor(keyStyle().textColor);
|
||||
getParentMathText()->setFontPointSize(keyStyle().fontSize*getParent()->getFontSizeMultiplier());
|
||||
getParentMathText()->setFontSpecial(keyStyle().fontName);
|
||||
getParentMathText()->parse(r.text);
|
||||
getParentMathText()->draw(painter, Qt::AlignLeft|Qt::AlignVCenter, textRect, getParent()->isDebugShowTextBoxesEnabled());
|
||||
drawEntrySample(r.id, painter, sampleRect);
|
||||
{
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaatmt(QString("JKQTPBaseKey[%1]::drawKey()::drawEntryText(r=%2,c=%3)::parse").arg(objectName()).arg(ir).arg(ic));
|
||||
#endif
|
||||
getParentMathText()->setFontColor(keyStyle().textColor);
|
||||
getParentMathText()->setFontPointSize(keyStyle().fontSize*getParent()->getFontSizeMultiplier());
|
||||
getParentMathText()->setFontSpecial(keyStyle().fontName);
|
||||
getParentMathText()->parse(r.text);
|
||||
}
|
||||
{
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaatmt(QString("JKQTPBaseKey[%1]::drawKey()::drawEntryText(r=%2,c=%3)::parse").arg(objectName()).arg(ir).arg(ic));
|
||||
#endif
|
||||
getParentMathText()->draw(painter, Qt::AlignLeft|Qt::AlignVCenter, textRect, getParent()->isDebugShowTextBoxesEnabled());
|
||||
}
|
||||
|
||||
if (drawDebugRects) {
|
||||
painter.save(); auto __finalpaintinner=JKQTPFinally([&painter]() {painter.restore();});
|
||||
@ -160,6 +173,7 @@ void JKQTPBaseKey::drawKey(JKQTPEnhancedPainter &painter, const QRectF &rect, co
|
||||
ir++;
|
||||
}
|
||||
xi.setX(xi.x()+c.calcColumnWidth(keyStyle().sampleLineLength*Xwid, keyStyle().xSeparation*Xwid)+keyStyle().columnSeparation*Xwid);
|
||||
ic++;
|
||||
}
|
||||
|
||||
}
|
||||
@ -167,13 +181,15 @@ void JKQTPBaseKey::drawKey(JKQTPEnhancedPainter &painter, const QRectF &rect, co
|
||||
|
||||
JKQTPBaseKey::KeySizeDescription JKQTPBaseKey::getSize(JKQTPEnhancedPainter &painter)
|
||||
{
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTPBaseKey[%1]::getSize()").arg(objectName()));
|
||||
#endif
|
||||
KeySizeDescription size;
|
||||
if (!keyStyle().visible) return size;
|
||||
|
||||
QFont kf(JKQTMathTextFontSpecifier::fromFontSpec(keyStyle().fontName).fontName(), keyStyle().fontSize);
|
||||
kf.setPointSizeF(keyStyle().fontSize*getParent()->getFontSizeMultiplier());
|
||||
const QFontMetricsF kfm(kf, painter.device());
|
||||
const qreal Xwid=kfm.boundingRect('X').width();
|
||||
const qreal Xwid=JKQTMathTextGetBoundingRect(kf,"X",painter.device()).width();
|
||||
|
||||
// calculate layout of the "table" of samples and labels
|
||||
const KeyLayoutDescription layout=getKeyLayout(painter);
|
||||
@ -190,9 +206,8 @@ void JKQTPBaseKey::calcLayoutSize(JKQTPEnhancedPainter &painter, KeySizeDescript
|
||||
{
|
||||
QFont kf(JKQTMathTextFontSpecifier::fromFontSpec(keyStyle().fontName).fontName(), keyStyle().fontSize);
|
||||
kf.setPointSizeF(keyStyle().fontSize*getParent()->getFontSizeMultiplier());
|
||||
const QFontMetricsF kfm(kf, painter.device());
|
||||
const qreal Xwid=kfm.boundingRect('X').width();
|
||||
const qreal FHeight=kfm.height();
|
||||
const qreal Xwid=JKQTMathTextGetBoundingRect(kf,"X",painter.device()).width();
|
||||
const qreal FHeight=JKQTMathTextGetFontHeight(kf, painter.device());
|
||||
|
||||
layout.requiredSize=extendLayoutSize(QSizeF(layout.d->calcOverallWidth(keyStyle().sampleLineLength*Xwid, keyStyle().xSeparation*Xwid, keyStyle().columnSeparation*Xwid),
|
||||
layout.d->calcOverallHeight(keyStyle().ySeparation*FHeight, keyStyle().sampleHeight*FHeight)), painter);
|
||||
@ -207,6 +222,9 @@ void JKQTPBaseKey::calcLayoutSize(JKQTPEnhancedPainter &painter, KeySizeDescript
|
||||
|
||||
void JKQTPBaseKey::modifySize(JKQTPEnhancedPainter &painter, KeySizeDescription ¤tKeyLayout, QSizeF preliminaryPlotSize)
|
||||
{
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTPBaseKey[%1]::modifySize()").arg(objectName()));
|
||||
#endif
|
||||
const auto lay=getLayout();
|
||||
if (lay==JKQTPKeyLayoutMultiColumn || lay==JKQTPKeyLayoutMultiRow) {
|
||||
std::function<bool(QSizeF, QSizeF)> fCompare=[](const QSizeF& requiredSize, const QSizeF& preliminaryPlotSize) {
|
||||
@ -264,11 +282,13 @@ void JKQTPBaseKey::setCurrentKeyStyle(const JKQTPKeyStyle &style)
|
||||
|
||||
JKQTPBaseKey::KeyLayoutDescription JKQTPBaseKey::getKeyLayout(JKQTPEnhancedPainter &painter)
|
||||
{
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTPBaseKey[%1]::getKeyLayout()").arg(objectName()));
|
||||
#endif
|
||||
QFont kf(JKQTMathTextFontSpecifier::fromFontSpec(keyStyle().fontName).fontName(), keyStyle().fontSize);
|
||||
kf.setPointSizeF(keyStyle().fontSize*getParent()->getFontSizeMultiplier());
|
||||
QFontMetricsF kfm(kf, painter.device());
|
||||
//const qreal Xwid=kfm.boundingRect('X').width();
|
||||
const qreal Fheight=kfm.height();
|
||||
//const qreal Xwid=JKQTMathTextGetBoundingRect(kf,"X",painter.device()).width();
|
||||
const qreal Fheight=JKQTMathTextGetFontHeight(kf, painter.device());
|
||||
//const double frameWidth=qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, getParent()->pt2px(painter, keyStyle().frameWidth*getParent()->getLineWidthMultiplier()));
|
||||
|
||||
|
||||
@ -303,10 +323,12 @@ JKQTPBaseKey::KeyLayoutDescription JKQTPBaseKey::getKeyLayout(JKQTPEnhancedPaint
|
||||
|
||||
QSizeF JKQTPBaseKey::extendLayoutSize(QSizeF rawLayoutSize, JKQTPEnhancedPainter& painter, QPointF *offset) const
|
||||
{
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTPBaseKey[%1]::extendLayoutSize()").arg(objectName()));
|
||||
#endif
|
||||
QFont kf(JKQTMathTextFontSpecifier::fromFontSpec(keyStyle().fontName).fontName(), keyStyle().fontSize);
|
||||
kf.setPointSizeF(keyStyle().fontSize*getParent()->getFontSizeMultiplier());
|
||||
QFontMetricsF kfm(kf, painter.device());
|
||||
const qreal Xwid=kfm.boundingRect('X').width();
|
||||
const qreal Xwid=JKQTMathTextGetBoundingRect(kf,"X",painter.device()).width();
|
||||
const double frameWidth=qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, getParent()->pt2px(painter, keyStyle().frameWidth*getParent()->getLineWidthMultiplier()));
|
||||
|
||||
if (rawLayoutSize.width()>0) rawLayoutSize.setWidth(rawLayoutSize.width()+2.0*keyStyle().xMargin*Xwid+2.0*frameWidth);
|
||||
@ -531,6 +553,9 @@ QColor JKQTPMainKey::getEntryColor(int item) const
|
||||
|
||||
void JKQTPMainKey::drawEntrySample(int item, JKQTPEnhancedPainter &painter, const QRectF &rect)
|
||||
{
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTPBaseKey[%1]::drawEntrySammple(%2)").arg(objectName()).arg(item));
|
||||
#endif
|
||||
auto g=getPlotElement(item);
|
||||
if (g) g->drawKeyMarker(painter, rect);
|
||||
}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 202 KiB |
Binary file not shown.
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 34 KiB |
Loading…
Reference in New Issue
Block a user