Fix mirroring a piece label.

This commit is contained in:
Roman Telezhynskyi 2022-02-19 21:17:51 +02:00
parent 460385c3ad
commit 8837bec33d
4 changed files with 174 additions and 93 deletions

View File

@ -47,6 +47,7 @@
#include "../vpapplication.h" #include "../vpapplication.h"
#include "compatibility.h"
#include "vlayoutpiecepath.h" #include "vlayoutpiecepath.h"
#include "vplacelabelitem.h" #include "vplacelabelitem.h"
@ -60,8 +61,82 @@ namespace
{ {
QColor mainColor = Qt::black; QColor mainColor = Qt::black;
QColor errorColor = Qt::red; QColor errorColor = Qt::red;
//---------------------------------------------------------------------------------------------------------------------
inline auto LineMatrix(const VPPiecePtr &piece, const QPointF &topLeft, qreal angle, const QPointF &linePos,
int maxLineWidth) -> QTransform
{
if (piece.isNull())
{
return {};
}
QTransform labelMatrix;
labelMatrix.translate(topLeft.x(), topLeft.y());
if (piece->IsMirror())
{
labelMatrix.scale(-1, 1);
labelMatrix.rotate(-angle);
labelMatrix.translate(-maxLineWidth, 0);
}
else
{
labelMatrix.rotate(angle);
}
labelMatrix.translate(linePos.x(), linePos.y()); // Each string has own position
labelMatrix *= piece->GetMatrix();
return labelMatrix;
} }
//---------------------------------------------------------------------------------------------------------------------
inline auto LineFont(const TextLine& tl, const QFont &base) -> QFont
{
QFont fnt = base;
fnt.setPixelSize(base.pixelSize() + tl.m_iFontSize);
fnt.setBold(tl.m_bold);
fnt.setItalic(tl.m_italic);
return fnt;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto LineText(const TextLine& tl, const QFontMetrics &fm, qreal width) -> QString
{
QString qsText = tl.m_qsText;
if (TextWidth(fm, qsText) > width)
{
qsText = fm.elidedText(qsText, Qt::ElideMiddle, static_cast<int>(width));
}
return qsText;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto LineAlign(const TextLine& tl, const QString &text, const QFontMetrics &fm, qreal width) -> qreal
{
const int lineWidth = TextWidth(fm, text);
qreal dX = 0;
if (tl.m_eAlign == 0 || (tl.m_eAlign & Qt::AlignLeft) > 0)
{
dX = 0;
}
else if ((tl.m_eAlign & Qt::AlignHCenter) > 0)
{
dX = (width - lineWidth)/2;
}
else if ((tl.m_eAlign & Qt::AlignRight) > 0)
{
dX = width - lineWidth;
}
return dX;
}
} // namespace
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VPGraphicsPiece::VPGraphicsPiece(const VPPiecePtr &piece, QGraphicsItem *parent) : VPGraphicsPiece::VPGraphicsPiece(const VPPiecePtr &piece, QGraphicsItem *parent) :
QGraphicsObject(parent), QGraphicsObject(parent),
@ -302,108 +377,63 @@ void VPGraphicsPiece::InitPieceLabel(const QVector<QPointF> &labelShape, const V
return; return;
} }
if (labelShape.count() > 2) if (labelShape.count() <= 2)
{ {
const qreal dW = QLineF(labelShape.at(0), labelShape.at(1)).length(); return;
const qreal dH = QLineF(labelShape.at(1), labelShape.at(2)).length(); }
const qreal angle = - QLineF(labelShape.at(0), labelShape.at(1)).angle();
qreal dY = 0;
QColor color = PieceColor();
for (int i = 0; i < tm.GetSourceLinesCount(); ++i) const qreal dW = QLineF(labelShape.at(0), labelShape.at(1)).length();
const qreal dH = QLineF(labelShape.at(1), labelShape.at(2)).length();
const qreal angle = - QLineF(labelShape.at(0), labelShape.at(1)).angle();
const QColor color = PieceColor();
const int maxLineWidth = tm.MaxLineWidth(static_cast<int>(dW));
qreal dY = 0;
for (int i = 0; i < tm.GetSourceLinesCount(); ++i)
{
const TextLine& tl = tm.GetSourceLine(i);
const QFont fnt = LineFont(tl, tm.GetFont());
const QFontMetrics fm(fnt);
if (m_textAsPaths)
{ {
const TextLine& tl = tm.GetSourceLine(i); dY += fm.height();
QFont fnt = tm.GetFont(); }
fnt.setPixelSize(tm.GetFont().pixelSize() + tl.m_iFontSize);
fnt.setBold(tl.m_bold);
fnt.setItalic(tl.m_italic);
QFontMetrics fm(fnt); if (dY > dH)
{
break;
}
if (m_textAsPaths) const QString qsText = LineText(tl, fm, dW);
{ const qreal dX = LineAlign(tl, qsText, fm, dW);
dY += fm.height(); // set up the rotation around top-left corner matrix
} const QTransform lineMatrix = LineMatrix(piece, labelShape.at(0), angle, QPointF(dX, dY), maxLineWidth);
if (dY > dH) if (m_textAsPaths)
{ {
break; QPainterPath path;
} path.addText(0, - static_cast<qreal>(fm.ascent())/6., fnt, qsText);
QString qsText = tl.m_qsText; auto* item = new QGraphicsPathItem(this);
#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) item->setPath(path);
if (fm.horizontalAdvance(qsText) > dW) item->setBrush(QBrush(color));
#else item->setTransform(lineMatrix);
if (fm.width(qsText) > dW) m_labelPathItems.append(item);
#endif
{
qsText = fm.elidedText(qsText, Qt::ElideMiddle, static_cast<int>(dW));
}
qreal dX = 0; dY += tm.GetSpacing();
if (tl.m_eAlign == 0 || (tl.m_eAlign & Qt::AlignLeft) > 0) }
{ else
dX = 0; {
} auto* item = new QGraphicsSimpleTextItem(this);
else if ((tl.m_eAlign & Qt::AlignHCenter) > 0) item->setFont(fnt);
{ item->setText(qsText);
#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) item->setBrush(QBrush(color));
dX = (dW - fm.horizontalAdvance(qsText))/2; item->setTransform(lineMatrix);
#else m_labelTextItems.append(item);
dX = (dW - fm.width(qsText))/2;
#endif
}
else if ((tl.m_eAlign & Qt::AlignRight) > 0)
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
dX = dW - fm.horizontalAdvance(qsText);
#else
dX = dW - fm.width(qsText);
#endif
}
// set up the rotation around top-left corner matrix dY += (fm.height() + tm.GetSpacing());
QTransform labelMatrix;
labelMatrix.translate(labelShape.at(0).x(), labelShape.at(0).y());
if (piece->IsMirror())
{
labelMatrix.scale(-1, 1);
labelMatrix.rotate(-angle);
labelMatrix.translate(-dW, 0);
labelMatrix.translate(dX, dY); // Each string has own position
}
else
{
labelMatrix.rotate(angle);
labelMatrix.translate(dX, dY); // Each string has own position
}
labelMatrix *= piece->GetMatrix();
if (m_textAsPaths)
{
QPainterPath path;
path.addText(0, - static_cast<qreal>(fm.ascent())/6., fnt, qsText);
auto* item = new QGraphicsPathItem(this);
item->setPath(path);
item->setBrush(QBrush(color));
item->setTransform(labelMatrix);
m_labelPathItems.append(item);
dY += tm.GetSpacing();
}
else
{
auto* item = new QGraphicsSimpleTextItem(this);
item->setFont(fnt);
item->setText(qsText);
item->setBrush(QBrush(color));
item->setTransform(labelMatrix);
m_labelTextItems.append(item);
dY += (fm.height() + tm.GetSpacing());
}
} }
} }
} }

View File

@ -491,6 +491,34 @@ auto VTextManager::GetSourceLine(int i) const -> const TextLine&
return m_liLines.at(i); return m_liLines.at(i);
} }
//---------------------------------------------------------------------------------------------------------------------
auto VTextManager::MaxLineWidth(int width) const -> int
{
int maxWidth = 0;
for (int i = 0; i < m_liLines.count(); ++i)
{
const TextLine& tl = m_liLines.at(i);
QFont fnt = m_font;
fnt.setPixelSize(fnt.pixelSize() + tl.m_iFontSize);
fnt.setBold(tl.m_bold);
fnt.setItalic(tl.m_italic);
QFontMetrics fm(fnt);
QString qsText = tl.m_qsText;
if (TextWidth(fm, qsText) > width)
{
qsText = fm.elidedText(qsText, Qt::ElideMiddle, width);
}
maxWidth = qMax(TextWidth(fm, qsText), maxWidth);
}
return maxWidth;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
/** /**
* @brief VTextManager::FitFontSize sets the font size just big enough, so that the text fits into rectangle of * @brief VTextManager::FitFontSize sets the font size just big enough, so that the text fits into rectangle of

View File

@ -90,6 +90,8 @@ public:
auto GetSourceLinesCount() const -> int; auto GetSourceLinesCount() const -> int;
auto GetSourceLine(int i) const -> const TextLine&; auto GetSourceLine(int i) const -> const TextLine&;
auto MaxLineWidth(int width) const -> int;
void Update(const QString& qsName, const VPieceLabelData& data, const VContainer *pattern); void Update(const QString& qsName, const VPieceLabelData& data, const VContainer *pattern);
void Update(VAbstractPattern* pDoc, const VContainer *pattern); void Update(VAbstractPattern* pDoc, const VContainer *pattern);

View File

@ -32,6 +32,7 @@
#include <QStringList> #include <QStringList>
#include <QSet> #include <QSet>
#include <QVector> #include <QVector>
#include <QFontMetrics>
class QPointF; class QPointF;
@ -253,4 +254,24 @@ inline auto SetIntersects(const QSet<T> &set1, const QSet<T> &set2) -> bool
#endif #endif
} }
//---------------------------------------------------------------------------------------------------------------------
inline auto TextWidth(const QFontMetrics &fm, const QString &text, int len = -1) -> int
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
return fm.horizontalAdvance(text, len);
#else
return fm.width(text, len);
#endif
}
//---------------------------------------------------------------------------------------------------------------------
inline auto TextWidthF(const QFontMetricsF &fm, const QString &text) -> qreal
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
return fm.horizontalAdvance(text);
#else
return fm.width(text);
#endif
}
#endif // COMPATIBILITY_H #endif // COMPATIBILITY_H