Fixed font size calculation, so that the app does not get stuck

--HG--
branch : feature
This commit is contained in:
BojanKverh 2016-12-14 00:56:30 +01:00
parent 9690d47df4
commit f6122ea8be
9 changed files with 133 additions and 231 deletions

View File

@ -148,10 +148,15 @@ void VLayoutDetail::SetDetail(const QString& qsName, const VPatternPieceData& da
// generate text
d->m_tmDetail.SetFont(font);
d->m_tmDetail.SetFontSize(data.GetFontSize());
int iFS = data.GetFontSize();
if (iFS < MIN_FONT_SIZE)
{
iFS = MIN_FONT_SIZE;
}
d->m_tmDetail.SetFontSize(iFS);
d->m_tmDetail.Update(qsName, data);
// this will generate the lines of text
d->m_tmDetail.SetFontSize(data.GetFontSize());
d->m_tmDetail.SetFontSize(iFS);
d->m_tmDetail.FitFontSize(data.GetLabelWidth(), data.GetLabelHeight());
}
@ -175,11 +180,17 @@ void VLayoutDetail::SetPatternInfo(const VAbstractPattern* pDoc, const VPatternI
// Generate text
d->m_tmPattern.SetFont(font);
d->m_tmPattern.SetFontSize(geom.GetFontSize());
int iFS = geom.GetFontSize();
if (iFS < MIN_FONT_SIZE)
{
iFS = MIN_FONT_SIZE;
}
d->m_tmPattern.SetFontSize(iFS);
d->m_tmPattern.Update(pDoc, dSize, dHeight);
// generate lines of text
d->m_tmPattern.SetFontSize(geom.GetFontSize());
d->m_tmPattern.SetFontSize(iFS);
d->m_tmPattern.FitFontSize(geom.GetLabelWidth(), geom.GetLabelHeight());
}
@ -553,8 +564,9 @@ void VLayoutDetail::CreateTextItems()
points.push_back(points.at(0));
// calculate the angle of rotation
qreal dAng = qAtan2(points.at(1).y() - points.at(0).y(), points.at(1).x() - points.at(0).x());
// calculate the label width
// calculate the label width and height
qreal dW = GetDistance(points.at(0), points.at(1));
qreal dH = GetDistance(points.at(1), points.at(2));
qreal dY = 0;
qreal dX;
// set up the rotation around top-left corner matrix
@ -562,16 +574,26 @@ void VLayoutDetail::CreateTextItems()
mat.translate(points.at(0).x(), points.at(0).y());
mat.rotate(qRadiansToDegrees(dAng));
for (int i = 0; i < d->m_tmDetail.GetOutputLinesCount(); ++i)
for (int i = 0; i < d->m_tmDetail.GetSourceLinesCount(); ++i)
{
const TextLine& tl = d->m_tmDetail.GetOutputLine(i);
const TextLine& tl = d->m_tmDetail.GetSourceLine(i);
QFont fnt = d->m_tmDetail.GetFont();
fnt.setPixelSize(d->m_tmDetail.GetFont().pixelSize() + tl.m_iFontSize);
fnt.setWeight(tl.m_eFontWeight);
fnt.setStyle(tl.m_eStyle);
dY += tl.m_iHeight;
// check if the next line will go out of bounds
if (dY > dH)
{
break;
}
QFontMetrics fm(fnt);
QString qsText = tl.m_qsText;
if (fm.width(qsText) > dW)
{
qsText = fm.elidedText(qsText, Qt::ElideRight, dW);
}
// find the correct horizontal offset, depending on the alignment flag
if ((tl.m_eAlign & Qt::AlignLeft) > 0)
{
@ -579,15 +601,15 @@ void VLayoutDetail::CreateTextItems()
}
else if ((tl.m_eAlign & Qt::AlignHCenter) > 0)
{
dX = (dW - fm.width(tl.m_qsText))/2;
dX = (dW - fm.width(qsText))/2;
}
else
{
dX = dW - fm.width(tl.m_qsText);
dX = dW - fm.width(qsText);
}
// create text path and add it to the list
QPainterPath path;
path.addText(dX, dY - (fm.height() - fm.ascent())/2, fnt, tl.m_qsText);
path.addText(dX, dY - (fm.height() - fm.ascent())/2, fnt, qsText);
d->m_liPP << mat.map(path);
dY += d->m_tmDetail.GetSpacing();
}
@ -600,36 +622,46 @@ void VLayoutDetail::CreateTextItems()
points.push_back(points.at(0));
qreal dAng = qAtan2(points.at(1).y() - points.at(0).y(), points.at(1).x() - points.at(0).x());
qreal dW = GetDistance(points.at(0), points.at(1));
qreal dH = GetDistance(points.at(1), points.at(2));
qreal dY = 0;
qreal dX;
QMatrix mat;
mat.translate(points.at(0).x(), points.at(0).y());
mat.rotate(qRadiansToDegrees(dAng));
for (int i = 0; i < d->m_tmPattern.GetOutputLinesCount(); ++i)
for (int i = 0; i < d->m_tmPattern.GetSourceLinesCount(); ++i)
{
const TextLine& tl = d->m_tmPattern.GetOutputLine(i);
const TextLine& tl = d->m_tmPattern.GetSourceLine(i);
QFont fnt = d->m_tmPattern.GetFont();
fnt.setPixelSize(d->m_tmPattern.GetFont().pixelSize() + tl.m_iFontSize);
fnt.setWeight(tl.m_eFontWeight);
fnt.setStyle(tl.m_eStyle);
dY += tl.m_iHeight;
if (dY > dH)
{
break;
}
QFontMetrics fm(fnt);
QString qsText = tl.m_qsText;
if (fm.width(qsText) > dW)
{
qsText = fm.elidedText(qsText, Qt::ElideRight, dW);
}
if ((tl.m_eAlign & Qt::AlignLeft) > 0)
{
dX = 0;
}
else if ((tl.m_eAlign & Qt::AlignHCenter) > 0)
{
dX = (dW - fm.width(tl.m_qsText))/2;
dX = (dW - fm.width(qsText))/2;
}
else
{
dX = dW - fm.width(tl.m_qsText);
dX = dW - fm.width(qsText);
}
QPainterPath path;
path.addText(dX, dY - (fm.height() - fm.ascent())/2, fnt, tl.m_qsText);
path.addText(dX, dY - (fm.height() - fm.ascent())/2, fnt, qsText);
d->m_liPP << mat.map(path);
dY += d->m_tmPattern.GetSpacing();
}
@ -658,7 +690,7 @@ QGraphicsItem* VLayoutDetail::GetTextItem(int i) const
if (d->mirror == true)
{
QVector<QPointF> points;
if (i < d->m_tmDetail.GetOutputLinesCount())
if (i < d->m_tmDetail.GetSourceLinesCount())
{
points = Map(Mirror(d->detailLabel));
}

View File

@ -32,6 +32,7 @@
#include <QLatin1String>
#include <QRegularExpression>
#include <QApplication>
#include <QtMath>
#include "../ifc/xml/vabstractpattern.h"
#include "../vpatterndb/vpatternpiecedata.h"
@ -52,7 +53,7 @@ TextLine::TextLine()
* @brief VTextManager::VTextManager constructor
*/
VTextManager::VTextManager()
:m_font(), m_liLines(), m_liOutput()
:m_font(), m_liLines()
{}
//---------------------------------------------------------------------------------------------------------------------
@ -64,7 +65,7 @@ VTextManager::~VTextManager()
//---------------------------------------------------------------------------------------------------------------------
VTextManager::VTextManager(const VTextManager &text)
: m_font(text.GetFont()), m_liLines(text.GetAllSourceLines()), m_liOutput(text.GetAllOutputLines())
: m_font(text.GetFont()), m_liLines(text.GetAllSourceLines())
{}
//---------------------------------------------------------------------------------------------------------------------
@ -76,7 +77,6 @@ VTextManager &VTextManager::operator=(const VTextManager &text)
}
m_font = text.GetFont();
m_liLines = text.GetAllSourceLines();
m_liOutput = text.GetAllOutputLines();
return *this;
}
@ -87,7 +87,7 @@ VTextManager &VTextManager::operator=(const VTextManager &text)
*/
int VTextManager::GetSpacing() const
{
return 2;
return 0;
}
//---------------------------------------------------------------------------------------------------------------------
@ -117,7 +117,14 @@ const QFont& VTextManager::GetFont() const
*/
void VTextManager::SetFontSize(int iFS)
{
m_font.setPixelSize(iFS);
if (iFS < MIN_FONT_SIZE)
{
m_font.setPixelSize(MIN_FONT_SIZE);
}
else
{
m_font.setPixelSize(iFS);
}
}
//---------------------------------------------------------------------------------------------------------------------
@ -145,16 +152,6 @@ void VTextManager::ClearSourceLines()
m_liLines.clear();
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief VTextManager::GetOutputLinesCount returns the number of output text lines
* @return number of output text lines
*/
int VTextManager::GetOutputLinesCount() const
{
return m_liOutput.count();
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief VTextManager::GetSourceLinesCount returns the number of input text lines
@ -165,69 +162,17 @@ int VTextManager::GetSourceLinesCount() const
return m_liLines.count();
}
//---------------------------------------------------------------------------------------------------------------------
QList<TextLine> VTextManager::GetAllOutputLines() const
{
return m_liOutput;
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief VTextManager::GetLine returns the i-th output text line
* @param i index of the output text line
* @return i-th output text line
* @brief VTextManager::GetSourceLine returns the reference to i-th text line
* @param i index of the requested line
* @return reference to the requested TextLine object
*/
const TextLine& VTextManager::GetOutputLine(int i) const
const TextLine& VTextManager::GetSourceLine(int i) const
{
return m_liOutput[i];
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief VTextManager::IsBigEnough Checks if rectangle of size (fW, fH) is big enough to hold the text with base font
* size iFontSize
* @param fW rectangle width
* @param fH rectangle height
* @param iFontSize base font size
* @param fMinW minimal required rectangle width to fit the text
* @param fMinH minimal required rectangle height to fit the text
* @return true, if rectangle of size (fW, fH)
*/
bool VTextManager::IsBigEnough(qreal fW, qreal fH, int iFontSize, qreal& fMinW, qreal& fMinH)
{
m_liOutput.clear();
QFont fnt = m_font;
int iY = 0;
fMinW = fW;
fMinH = fH;
for (int i = 0; i < m_liLines.count(); ++i)
{
const TextLine& tl = m_liLines.at(i);
TextLine tlOut = tl;
fnt.setPixelSize(iFontSize + tl.m_iFontSize);
QFontMetrics fm(fnt);
int iHorSp = fm.width(" ");
tlOut.m_iHeight = fm.height();
QStringList qslLines = SplitString(tlOut.m_qsText, fW, fm);
for (int iL = 0; iL < qslLines.count(); ++iL)
{
// check if every line fits within the label width
if (fm.width(qslLines[iL]) + iHorSp > fW)
{
fMinW = fm.width(qslLines[iL]) + iHorSp;
return false;
}
tlOut.m_qsText = qslLines[iL];
m_liOutput << tlOut;
iY += tlOut.m_iHeight + GetSpacing();
}
}
if (iY > fH)
{
fMinH = iY;
}
return iY <= fH;
Q_ASSERT(i >= 0);
Q_ASSERT(i < m_liLines.count());
return m_liLines[i];
}
//---------------------------------------------------------------------------------------------------------------------
@ -239,19 +184,43 @@ bool VTextManager::IsBigEnough(qreal fW, qreal fH, int iFontSize, qreal& fMinW,
*/
void VTextManager::FitFontSize(qreal fW, qreal fH)
{
int iFontSize = GetFont().pixelSize();
qreal fMinW;
qreal fMinH;
int iFS = 3*qFloor(fH/GetSourceLinesCount())/4;
if (iFS < MIN_FONT_SIZE)
{
iFS = MIN_FONT_SIZE;
}
while (IsBigEnough(fW, fH, iFontSize, fMinW, fMinH) == true && iFontSize <= MAX_FONT_SIZE)
// get ratio between char width and height
int iMaxLen = 0;
int iTW;
QFont fnt;
for (int i = 0; i < GetSourceLinesCount(); ++i)
{
++iFontSize;
const TextLine& tl = GetSourceLine(i);
fnt = m_font;
fnt.setPixelSize(iFS + tl.m_iFontSize);
fnt.setWeight(tl.m_eFontWeight);
fnt.setStyle(tl.m_eStyle);
QFontMetrics fm(fnt);
iTW = fm.width(GetSourceLine(i).m_qsText);
if (iTW > iMaxLen)
{
iMaxLen = iTW;
}
}
while (IsBigEnough(fW, fH, iFontSize, fMinW, fMinH) == false && iFontSize >= MIN_FONT_SIZE)
if (iMaxLen > fW)
{
--iFontSize;
iFS = qFloor(iFS*fW/iMaxLen);
}
SetFontSize(iFontSize);
iFS = qMax(MIN_FONT_SIZE, iFS);
int iH = 4*iFS/3;
SetFontSize(iFS);
for (int i = 0; i < GetSourceLinesCount(); ++i)
{
m_liLines[i].m_iHeight = iH;
}
qDebug() << "Font size" << GetSourceLinesCount() << iFS;
}
//---------------------------------------------------------------------------------------------------------------------
@ -404,64 +373,5 @@ void VTextManager::Update(const VAbstractPattern *pDoc, qreal dSize, qreal dHeig
tl.m_iFontSize = 0;
AddSourceLine(tl);
}
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief VTextManager::SplitString splits the string into several lines, which all fit into width fW
* @param qs string to split
* @param fW required width of every output string
* @param fm font metrics of the font used
* @return list of strings, each of which is not wider than fW using the font metrics fm
*/
QStringList VTextManager::SplitString(const QString &qs, qreal fW, const QFontMetrics &fm)
{
QRegularExpression reg("\\s+");
// split the string into words
QStringList qslWords = qs.split(reg);
QStringList qslLines;
QString qsCurrent;
for (int i = 0; i < qslWords.count(); ++i)
{
if (qsCurrent.length() > 0)
{
qsCurrent += QLatin1String(" ");
}
// check if another word can be added into current line
if (fm.width(qsCurrent + qslWords[i]) > fW)
{
// if not, add the current line into the list of text lines
if (qsCurrent.isEmpty() == false)
{
qslLines << qsCurrent;
}
// and set the current line to contain the current word
qsCurrent = qslWords[i];
}
else
{
qsCurrent += qslWords[i];
}
}
qslLines << qsCurrent;
int i = 0;
int iHorSp = fm.width(" ");
while (i < qslLines.count()) {
if (fm.width(qslLines[i]) + iHorSp > fW) {
int iPos = qslLines[i].length() >> 1;
QString qs1 = qslLines[i].left(iPos);
QString qs2 = qslLines[i].mid(iPos);
qslLines[i] = qs1;
qslLines.insert(i + 1, qs2);
} else {
++i;
}
}
return qslLines;
}

View File

@ -87,23 +87,14 @@ public:
void AddSourceLine(const TextLine& tl);
void ClearSourceLines();
int GetSourceLinesCount() const;
int GetOutputLinesCount() const;
QList<TextLine> GetAllOutputLines() const;
const TextLine& GetOutputLine(int i) const;
bool IsBigEnough(qreal fW, qreal fH, int iFontSize, qreal& fMinW, qreal& fMinH);
const TextLine& GetSourceLine(int i) const;
void Update(const QString& qsName, const VPatternPieceData& data);
void Update(const VAbstractPattern* pDoc, qreal dSize, qreal dHeight);
protected:
static QStringList SplitString(const QString& qs, qreal fW, const QFontMetrics& fm);
private:
QFont m_font;
QList<TextLine> m_liLines;
QList<TextLine> m_liOutput;
};
#endif // VTEXTMANAGER_H

View File

@ -32,15 +32,9 @@ class QPointF;
//---------------------------------------------------------------------------------------------------------------------
VPatternInfoGeometry::VPatternInfoGeometry()
:m_ptPos(0, 0), m_dLabelWidth(0), m_dLabelHeight(0), m_iFontSize(MIN_FONT_SIZE),
:m_ptPos(0, 0), m_dLabelWidth(0), m_dLabelHeight(0), m_iFontSize(0),
m_dRotation(0), m_bVisible(true)
{
m_iFontSize = MIN_FONT_SIZE;
// 0 means unknown width
m_dLabelWidth = 0;
m_dLabelHeight = 0;
m_dRotation = 0;
}
{}
//---------------------------------------------------------------------------------------------------------------------
QPointF VPatternInfoGeometry::GetPos() const
@ -87,14 +81,7 @@ int VPatternInfoGeometry::GetFontSize() const
//---------------------------------------------------------------------------------------------------------------------
void VPatternInfoGeometry::SetFontSize(int iSize)
{
if (iSize >= MIN_FONT_SIZE)
{
m_iFontSize = iSize;
}
else
{
m_iFontSize = MIN_FONT_SIZE;
}
m_iFontSize = iSize;
}
//---------------------------------------------------------------------------------------------------------------------

View File

@ -29,8 +29,6 @@
#ifndef VPATTERNINFOGEOMETRY_H
#define VPATTERNINFOGEOMETRY_H
#define MIN_FONT_SIZE 12
#include <QPointF>
#include <QtGlobal>

View File

@ -38,7 +38,7 @@ MaterialCutPlacement::MaterialCutPlacement()
//---------------------------------------------------------------------------------------------------------------------
VPatternPieceData::VPatternPieceData()
:m_qsLetter(), m_conMCP(), m_ptPos(0, 0), m_dLabelWidth(0), m_dLabelHeight(0),
m_iFontSize(MIN_FONT_SIZE), m_dRotation(0), m_bVisible(true)
m_iFontSize(0), m_dRotation(0), m_bVisible(true)
{}
//---------------------------------------------------------------------------------------------------------------------
@ -149,14 +149,7 @@ int VPatternPieceData::GetFontSize() const
//---------------------------------------------------------------------------------------------------------------------
void VPatternPieceData::SetFontSize(int iSize)
{
if (iSize >= MIN_FONT_SIZE)
{
m_iFontSize = iSize;
}
else
{
m_iFontSize = MIN_FONT_SIZE;
}
m_iFontSize = iSize;
}
//---------------------------------------------------------------------------------------------------------------------

View File

@ -29,8 +29,6 @@
#ifndef VPATTERNPIECEDATA_H
#define VPATTERNPIECEDATA_H
#define MIN_FONT_SIZE 12
#include <QList>
#include <QPointF>
#include <QSet>

View File

@ -106,16 +106,30 @@ void VTextGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem
painter->setPen(Qt::black);
QFont fnt = m_tm.GetFont();
int iW = qFloor(boundingRect().width());
// draw text lines
int iY = 0;
for (int i = 0; i < m_tm.GetOutputLinesCount(); ++i)
for (int i = 0; i < m_tm.GetSourceLinesCount(); ++i)
{
const TextLine& tl = m_tm.GetOutputLine(i);
const TextLine& tl = m_tm.GetSourceLine(i);
// check if the next line will go out of bounds
if (iY + tl.m_iHeight > boundingRect().height())
{
break;
}
fnt.setPixelSize(m_tm.GetFont().pixelSize() + tl.m_iFontSize);
fnt.setWeight(tl.m_eFontWeight);
fnt.setStyle(tl.m_eStyle);
QString qsText = tl.m_qsText;
QFontMetrics fm(fnt);
if (fm.width(qsText) > iW)
{
qsText = fm.elidedText(qsText, Qt::ElideRight, iW);
}
painter->setFont(fnt);
painter->drawText(0, iY, qRound(boundingRect().width()), tl.m_iHeight, tl.m_eAlign, tl.m_qsText);
painter->drawText(0, iY, iW, tl.m_iHeight, tl.m_eAlign, qsText);
iY += tl.m_iHeight + m_tm.GetSpacing();
}
@ -189,13 +203,13 @@ bool VTextGraphicsItem::IsIdle() const
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief VTextGraphicsItem::AddLine adds a line of text to the label list. If necessary, it also resizes the
* label bounding box until it is big enough to contain all the text
* @brief VTextGraphicsItem::AddLine adds a line of text to the label list.
* @param tl line of text to add
*/
void VTextGraphicsItem::AddLine(const TextLine& tl)
{
m_tm.AddSourceLine(tl);
/*
qreal fW = MIN_W;
qreal fH = m_iMinH;
qreal fMinW;
@ -212,6 +226,7 @@ void VTextGraphicsItem::AddLine(const TextLine& tl)
{
setPos(m_rectBoundingBox.left() + dX, m_rectBoundingBox.top() + dY);
}
*/
}
//---------------------------------------------------------------------------------------------------------------------
@ -348,7 +363,7 @@ void VTextGraphicsItem::UpdateData(const VAbstractPattern* pDoc, qreal dSize, qr
*/
int VTextGraphicsItem::GetTextLines() const
{
return m_tm.GetOutputLinesCount();
return m_tm.GetSourceLinesCount();
}
//---------------------------------------------------------------------------------------------------------------------
@ -589,33 +604,6 @@ void VTextGraphicsItem::UpdateBox()
*/
void VTextGraphicsItem::CorrectLabel()
{
int iFS = m_tm.GetFont().pixelSize();
qreal fMinW;
qreal fMinH;
// increase the font size until the bounding rect is not big enough
while (
iFS < MAX_FONT_SIZE &&
m_tm.IsBigEnough(m_rectBoundingBox.width(), m_rectBoundingBox.height(), iFS, fMinW, fMinH) == true
)
{
++iFS;
}
// decrease the font size until the bounding rect is big enough
while (m_tm.IsBigEnough(m_rectBoundingBox.width(), m_rectBoundingBox.height(), iFS, fMinW, fMinH) == false)
{
if (iFS > MIN_FONT_SIZE)
{
--iFS;
}
else
{
SetSize(fMinW, fMinH);
}
qDebug() << "DEC FONT" << iFS << m_rectBoundingBox.width() << fMinW;
}
qreal dX;
qreal dY;
QRectF rectBB;
@ -626,7 +614,7 @@ void VTextGraphicsItem::CorrectLabel()
// put the label inside the pattern
setPos(pos().x() + dX, pos().y() + dY);
}
m_tm.SetFontSize(iFS);
m_tm.FitFontSize(m_rectBoundingBox.width(), m_rectBoundingBox.height());
UpdateBox();
}

View File

@ -837,7 +837,12 @@ void VToolDetail::UpdateLabel()
if (data.IsVisible() == true)
{
QFont fnt = qApp->font();
fnt.setPixelSize(data.GetFontSize());
int iFS = data.GetFontSize();
if (iFS < MIN_FONT_SIZE)
{
iFS = MIN_FONT_SIZE;
}
fnt.setPixelSize(iFS);
dataLabel->SetFont(fnt);
dataLabel->SetSize(data.GetLabelWidth(), data.GetLabelHeight());
dataLabel->UpdateData(detail.getName(), data);