Compare commits

...

2 commits

Author SHA1 Message Date
Roman Telezhynskyi d4f14ab1d5 Lupdate. 2023-11-29 16:44:49 +02:00
Roman Telezhynskyi e9565b3e75 Horizontal piece flipping. 2023-11-29 16:40:36 +02:00
38 changed files with 4428 additions and 4084 deletions

View file

@ -59,6 +59,7 @@
- New tools: Arc start point, Arc end point. - New tools: Arc start point, Arc end point.
- Optimize U-notch shape. - Optimize U-notch shape.
- New feature. Boundary together with notches. - New feature. Boundary together with notches.
- Puzzle app. Horizontal piece flipping.
# Valentina 0.7.52 September 12, 2022 # Valentina 0.7.52 September 12, 2022
- Fix crash when default locale is ru. - Fix crash when default locale is ru.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -144,7 +144,7 @@ VPPiece::VPPiece(const VLayoutPiece &layoutPiece)
if (IsForceFlipping()) if (IsForceFlipping())
{ {
Flip(); FlipVertically();
} }
} }
@ -200,7 +200,8 @@ void VPPiece::ClearTransformations()
const QPointF offset = MappedDetailBoundingRect().topLeft(); const QPointF offset = MappedDetailBoundingRect().topLeft();
Translate(-offset.x(), -offset.y()); Translate(-offset.x(), -offset.y());
SetMirror(false); SetVerticallyFlipped(false);
SetHorizontallyFlipped(false);
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -287,7 +288,7 @@ void VPPiece::SetGrainline(const VPieceGrainline &grainline)
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPPiece::Flip() void VPPiece::FlipVertically()
{ {
QTransform pieceMatrix = GetMatrix(); QTransform pieceMatrix = GetMatrix();
QPointF center = pieceMatrix.map(DetailBoundingRect().center()); QPointF center = pieceMatrix.map(DetailBoundingRect().center());
@ -299,7 +300,23 @@ void VPPiece::Flip()
pieceMatrix *= m; pieceMatrix *= m;
SetMatrix(pieceMatrix); SetMatrix(pieceMatrix);
SetMirror(!IsMirror()); SetVerticallyFlipped(!IsVerticallyFlipped());
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::FlipHorizontally()
{
QTransform pieceMatrix = GetMatrix();
QPointF center = pieceMatrix.map(DetailBoundingRect().center());
QTransform m;
m.translate(0, center.y());
m.scale(1, -1);
m.translate(0, -center.y());
pieceMatrix *= m;
SetMatrix(pieceMatrix);
SetHorizontallyFlipped(!IsHorizontallyFlipped());
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------

View file

@ -97,9 +97,10 @@ public:
void SetGrainline(const VPieceGrainline &grainline); void SetGrainline(const VPieceGrainline &grainline);
/** /**
* @brief Flip horizontally mirror around center of bounding rect * @brief Flip verticvally mirror around center of bounding rect
*/ */
void Flip(); void FlipVertically();
void FlipHorizontally();
auto OutOfBound() const -> bool; auto OutOfBound() const -> bool;
void SetOutOfBound(bool newOutOfBound); void SetOutOfBound(bool newOutOfBound);

View file

@ -72,7 +72,7 @@ namespace
{ {
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
inline auto LineMatrix(const VPPiecePtr &piece, const QPointF &topLeft, qreal angle, const QPointF &linePos, inline auto LineMatrix(const VPPiecePtr &piece, const QPointF &topLeft, qreal angle, const QPointF &linePos,
int maxLineWidth) -> QTransform int maxLineWidth, qreal maxLabelHeight) -> QTransform
{ {
if (piece.isNull()) if (piece.isNull())
{ {
@ -82,12 +82,22 @@ inline auto LineMatrix(const VPPiecePtr &piece, const QPointF &topLeft, qreal an
QTransform labelMatrix; QTransform labelMatrix;
labelMatrix.translate(topLeft.x(), topLeft.y()); labelMatrix.translate(topLeft.x(), topLeft.y());
if (piece->IsMirror()) if (piece->IsVerticallyFlipped() || piece->IsHorizontallyFlipped())
{
if (piece->IsVerticallyFlipped())
{ {
labelMatrix.scale(-1, 1); labelMatrix.scale(-1, 1);
labelMatrix.rotate(-angle); labelMatrix.rotate(-angle);
labelMatrix.translate(-maxLineWidth, 0); labelMatrix.translate(-maxLineWidth, 0);
} }
if (piece->IsHorizontallyFlipped())
{
labelMatrix.scale(1, -1);
labelMatrix.rotate(-angle);
labelMatrix.translate(0, -maxLabelHeight);
}
}
else else
{ {
labelMatrix.rotate(angle); labelMatrix.rotate(angle);
@ -169,6 +179,72 @@ inline auto SelectionBrush() -> QBrush
{ {
return {QColor(255, 160, 160, 60)}; return {QColor(255, 160, 160, 60)};
} }
//---------------------------------------------------------------------------------------------------------------------
auto LabelHeightSVGFont(const VPPiecePtr &piece, const QVector<TextLine> &labelLines, const VSvgFont &svgFont,
const VSvgFontDatabase *db, qreal penWidth, qreal dH, int spacing) -> qreal
{
qreal labelHeight = 0;
if (piece->IsHorizontallyFlipped())
{
for (int i = 0; i < labelLines.size(); ++i)
{
const VSvgFont fnt = LineFont(labelLines.at(i), svgFont);
VSvgFontEngine engine = db->FontEngine(fnt);
const qreal lineHeight = engine.FontHeight() + penWidth;
if (labelHeight + lineHeight > dH)
{
break;
}
if (i < labelLines.size() - 1)
{
labelHeight += lineHeight + spacing;
}
else
{
labelHeight += lineHeight;
}
}
}
return labelHeight;
}
//---------------------------------------------------------------------------------------------------------------------
auto LabelHeightOutlineFont(const VPPiecePtr &piece, const QVector<TextLine> &labelLines, const QFont &font,
bool textAsPaths, qreal penWidth, qreal dH, int spacing) -> qreal
{
qreal labelHeight = 0;
if (piece->IsHorizontallyFlipped())
{
for (int i = 0; i < labelLines.size(); ++i)
{
const QFont fnt = LineFont(labelLines.at(i), font);
QFontMetrics fm(fnt);
const qreal lineHeight = textAsPaths ? fm.height() + penWidth : fm.height();
if (labelHeight + lineHeight > dH)
{
break;
}
if (i < labelLines.size() - 1)
{
labelHeight += lineHeight + spacing;
}
else
{
labelHeight += lineHeight;
}
}
}
return labelHeight;
}
} // namespace } // namespace
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -441,6 +517,8 @@ void VPGraphicsPiece::InitPieceLabelSVGFont(const QVector<QPointF> &labelShape,
const QVector<TextLine> labelLines = tm.GetLabelSourceLines(qFloor(dW), svgFont, penWidth); const QVector<TextLine> labelLines = tm.GetLabelSourceLines(qFloor(dW), svgFont, penWidth);
const qreal labelHeight = LabelHeightSVGFont(piece, labelLines, svgFont, db, penWidth, dH, tm.GetSpacing());
for (const auto &tl : labelLines) for (const auto &tl : labelLines)
{ {
const VSvgFont fnt = LineFont(tl, svgFont); const VSvgFont fnt = LineFont(tl, svgFont);
@ -454,7 +532,8 @@ void VPGraphicsPiece::InitPieceLabelSVGFont(const QVector<QPointF> &labelShape,
const QString qsText = tl.m_qsText; const QString qsText = tl.m_qsText;
const qreal dX = LineAlign(tl, qsText, engine, dW, penWidth); const qreal dX = LineAlign(tl, qsText, engine, dW, penWidth);
// set up the rotation around top-left corner matrix // set up the rotation around top-left corner matrix
const QTransform lineMatrix = LineMatrix(piece, labelShape.at(0), angle, QPointF(dX, dY), maxLineWidth); const QTransform lineMatrix =
LineMatrix(piece, labelShape.at(0), angle, QPointF(dX, dY), maxLineWidth, labelHeight);
auto *item = new QGraphicsPathItem(this); auto *item = new QGraphicsPathItem(this);
item->setPath(engine.DrawPath(QPointF(), qsText)); item->setPath(engine.DrawPath(QPointF(), qsText));
@ -508,6 +587,9 @@ void VPGraphicsPiece::InitPieceLabelOutlineFont(const QVector<QPointF> &labelSha
const QVector<TextLine> labelLines = tm.GetLabelSourceLines(qFloor(dW), tm.GetFont()); const QVector<TextLine> labelLines = tm.GetLabelSourceLines(qFloor(dW), tm.GetFont());
const qreal labelHeight =
LabelHeightOutlineFont(piece, labelLines, tm.GetFont(), textAsPaths, penWidth, dH, tm.GetSpacing());
for (const auto &tl : labelLines) for (const auto &tl : labelLines)
{ {
const QFont fnt = LineFont(tl, tm.GetFont()); const QFont fnt = LineFont(tl, tm.GetFont());
@ -528,7 +610,8 @@ void VPGraphicsPiece::InitPieceLabelOutlineFont(const QVector<QPointF> &labelSha
const QString qsText = tl.m_qsText; const QString qsText = tl.m_qsText;
const qreal dX = LineAlign(tl, qsText, fm, dW); const qreal dX = LineAlign(tl, qsText, fm, dW);
// set up the rotation around top-left corner matrix // set up the rotation around top-left corner matrix
const QTransform lineMatrix = LineMatrix(piece, labelShape.at(0), angle, QPointF(dX, dY), maxLineWidth); const QTransform lineMatrix =
LineMatrix(piece, labelShape.at(0), angle, QPointF(dX, dY), maxLineWidth, labelHeight);
if (textAsPaths) if (textAsPaths)
{ {

View file

@ -782,7 +782,7 @@ void VPMainWindow::InitPropertyTabCurrentPiece()
} }
}); });
connect(ui->checkBoxCurrentPieceMirrorPiece, &QCheckBox::toggled, this, connect(ui->checkBoxCurrentPieceVerticallyFlipped, &QCheckBox::toggled, this,
[this](bool checked) [this](bool checked)
{ {
QList<VPPiecePtr> selectedPieces = SelectedPieces(); QList<VPPiecePtr> selectedPieces = SelectedPieces();
@ -791,9 +791,28 @@ void VPMainWindow::InitPropertyTabCurrentPiece()
const VPPiecePtr &selectedPiece = selectedPieces.constFirst(); const VPPiecePtr &selectedPiece = selectedPieces.constFirst();
if (not selectedPiece.isNull()) if (not selectedPiece.isNull())
{ {
if (selectedPiece->IsMirror() != checked) if (selectedPiece->IsVerticallyFlipped() != checked)
{ {
selectedPiece->Flip(); selectedPiece->FlipVertically();
LayoutWasSaved(false);
emit m_layout->PieceTransformationChanged(selectedPiece);
}
}
}
});
connect(ui->checkBoxCurrentPieceHorizontallyFlipped, &QCheckBox::toggled, this,
[this](bool checked)
{
QList<VPPiecePtr> selectedPieces = SelectedPieces();
if (selectedPieces.size() == 1)
{
const VPPiecePtr &selectedPiece = selectedPieces.constFirst();
if (not selectedPiece.isNull())
{
if (selectedPiece->IsHorizontallyFlipped() != checked)
{
selectedPiece->FlipHorizontally();
LayoutWasSaved(false); LayoutWasSaved(false);
emit m_layout->PieceTransformationChanged(selectedPiece); emit m_layout->PieceTransformationChanged(selectedPiece);
} }
@ -1287,10 +1306,11 @@ void VPMainWindow::SetPropertyTabCurrentPieceData()
SetLineEditValue(ui->lineEditCurrentPieceGradationId, selectedPiece->GetGradationId()); SetLineEditValue(ui->lineEditCurrentPieceGradationId, selectedPiece->GetGradationId());
SetCheckBoxValue(ui->checkBoxCurrentPieceShowSeamline, not selectedPiece->IsHideMainPath()); SetCheckBoxValue(ui->checkBoxCurrentPieceShowSeamline, not selectedPiece->IsHideMainPath());
SetCheckBoxValue(ui->checkBoxCurrentPieceMirrorPiece, selectedPiece->IsMirror()); SetCheckBoxValue(ui->checkBoxCurrentPieceVerticallyFlipped, selectedPiece->IsVerticallyFlipped());
SetCheckBoxValue(ui->checkBoxCurrentPieceHorizontallyFlipped, selectedPiece->IsHorizontallyFlipped());
const bool disableFlipping = selectedPiece->IsForbidFlipping() || selectedPiece->IsForceFlipping(); const bool disableFlipping = selectedPiece->IsForbidFlipping() || selectedPiece->IsForceFlipping();
ui->checkBoxCurrentPieceMirrorPiece->setDisabled(disableFlipping); ui->checkBoxCurrentPieceVerticallyFlipped->setDisabled(disableFlipping);
if (not ui->checkBoxRelativeTranslation->isChecked()) if (not ui->checkBoxRelativeTranslation->isChecked())
{ {

View file

@ -279,8 +279,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>392</width> <width>378</width>
<height>700</height> <height>707</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_23"> <layout class="QVBoxLayout" name="verticalLayout_23">
@ -624,9 +624,16 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_9"> <layout class="QVBoxLayout" name="verticalLayout_9">
<item> <item>
<widget class="QCheckBox" name="checkBoxCurrentPieceMirrorPiece"> <widget class="QCheckBox" name="checkBoxCurrentPieceVerticallyFlipped">
<property name="text"> <property name="text">
<string>Mirror piece</string> <string>Vertically flipped</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxCurrentPieceHorizontallyFlipped">
<property name="text">
<string>Horizontally flipped</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -2416,7 +2423,7 @@
<tabstop>lineEditCurrentPieceName</tabstop> <tabstop>lineEditCurrentPieceName</tabstop>
<tabstop>plainTextEditCurrentPieceUUID</tabstop> <tabstop>plainTextEditCurrentPieceUUID</tabstop>
<tabstop>checkBoxCurrentPieceShowSeamline</tabstop> <tabstop>checkBoxCurrentPieceShowSeamline</tabstop>
<tabstop>checkBoxCurrentPieceMirrorPiece</tabstop> <tabstop>checkBoxCurrentPieceVerticallyFlipped</tabstop>
<tabstop>doubleSpinBoxCurrentPieceAngle</tabstop> <tabstop>doubleSpinBoxCurrentPieceAngle</tabstop>
<tabstop>doubleSpinBoxCurrentPieceBoxPositionX</tabstop> <tabstop>doubleSpinBoxCurrentPieceBoxPositionX</tabstop>
<tabstop>doubleSpinBoxCurrentPieceBoxPositionY</tabstop> <tabstop>doubleSpinBoxCurrentPieceBoxPositionY</tabstop>
@ -2434,8 +2441,8 @@
</resources> </resources>
<connections/> <connections/>
<buttongroups> <buttongroups>
<buttongroup name="buttonGroupTileOrientation"/>
<buttongroup name="buttonGroupSheetOrientation"/>
<buttongroup name="buttonGroupRotationDirection"/> <buttongroup name="buttonGroupRotationDirection"/>
<buttongroup name="buttonGroupSheetOrientation"/>
<buttongroup name="buttonGroupTileOrientation"/>
</buttongroups> </buttongroups>
</ui> </ui>

View file

@ -511,7 +511,8 @@ void VPLayoutFileReader::ReadPiece(const VPPiecePtr &piece)
piece->SetXScale(ReadAttributeDouble(attribs, ML::AttrXScale, QChar('1'))); piece->SetXScale(ReadAttributeDouble(attribs, ML::AttrXScale, QChar('1')));
piece->SetYScale(ReadAttributeDouble(attribs, ML::AttrYScale, QChar('1'))); piece->SetYScale(ReadAttributeDouble(attribs, ML::AttrYScale, QChar('1')));
piece->SetZValue(ReadAttributeDouble(attribs, ML::AttrZValue, QChar('1'))); piece->SetZValue(ReadAttributeDouble(attribs, ML::AttrZValue, QChar('1')));
piece->SetMirror(ReadAttributeBool(attribs, ML::AttrMirrored, falseStr)); piece->SetVerticallyFlipped(ReadAttributeBool(attribs, ML::AttrVerticallyFlipped, falseStr));
piece->SetHorizontallyFlipped(ReadAttributeBool(attribs, ML::AttrHorizontallyFlipped, falseStr));
piece->SetForbidFlipping(ReadAttributeBool(attribs, ML::AttrForbidFlipping, falseStr)); piece->SetForbidFlipping(ReadAttributeBool(attribs, ML::AttrForbidFlipping, falseStr));
piece->SetForceFlipping(ReadAttributeBool(attribs, ML::AttrForceFlipping, falseStr)); piece->SetForceFlipping(ReadAttributeBool(attribs, ML::AttrForceFlipping, falseStr));
piece->SetFollowGrainline(ReadAttributeBool(attribs, ML::AttrFollowGrainline, falseStr)); piece->SetFollowGrainline(ReadAttributeBool(attribs, ML::AttrFollowGrainline, falseStr));

View file

@ -260,8 +260,10 @@ void VPLayoutFileWriter::WritePiece(const VPPiecePtr &piece)
writeStartElement(ML::TagPiece); writeStartElement(ML::TagPiece);
SetAttribute(ML::AttrUID, piece->GetUUID().toString()); SetAttribute(ML::AttrUID, piece->GetUUID().toString());
SetAttribute(ML::AttrName, piece->GetName()); SetAttribute(ML::AttrName, piece->GetName());
SetAttributeOrRemoveIf<bool>(ML::AttrMirrored, piece->IsMirror(), SetAttributeOrRemoveIf<bool>(ML::AttrVerticallyFlipped, piece->IsVerticallyFlipped(),
[](bool mirrored) noexcept { return not mirrored; }); [](bool flipped) noexcept { return not flipped; });
SetAttributeOrRemoveIf<bool>(ML::AttrHorizontallyFlipped, piece->IsHorizontallyFlipped(),
[](bool flipped) noexcept { return not flipped; });
SetAttributeOrRemoveIf<bool>(ML::AttrForbidFlipping, piece->IsForbidFlipping(), SetAttributeOrRemoveIf<bool>(ML::AttrForbidFlipping, piece->IsForbidFlipping(),
[](bool forbid) noexcept { return not forbid; }); [](bool forbid) noexcept { return not forbid; });
SetAttributeOrRemoveIf<bool>(ML::AttrForceFlipping, piece->IsForceFlipping(), SetAttributeOrRemoveIf<bool>(ML::AttrForceFlipping, piece->IsForceFlipping(),

View file

@ -84,7 +84,8 @@ const QString AttrLength = QStringLiteral("length");
const QString AttrFollowGrainline = QStringLiteral("followGrainline"); // NOLINT(cert-err58-cpp) const QString AttrFollowGrainline = QStringLiteral("followGrainline"); // NOLINT(cert-err58-cpp)
const QString AttrBoundaryTogetherWithNotches = QStringLiteral("boundaryTogetherWithNotches"); // NOLINT(cert-err58-cpp) const QString AttrBoundaryTogetherWithNotches = QStringLiteral("boundaryTogetherWithNotches"); // NOLINT(cert-err58-cpp)
const QString AttrUID = QStringLiteral("uid"); // NOLINT(cert-err58-cpp) const QString AttrUID = QStringLiteral("uid"); // NOLINT(cert-err58-cpp)
const QString AttrMirrored = QStringLiteral("mirrored"); // NOLINT(cert-err58-cpp) const QString AttrVerticallyFlipped = QStringLiteral("verticallyFlipped"); // NOLINT(cert-err58-cpp)
const QString AttrHorizontallyFlipped = QStringLiteral("horizontallyFlipped"); // NOLINT(cert-err58-cpp)
const QString AttrForbidFlipping = QStringLiteral("forbidFlipping"); // NOLINT(cert-err58-cpp) const QString AttrForbidFlipping = QStringLiteral("forbidFlipping"); // NOLINT(cert-err58-cpp)
const QString AttrForceFlipping = QStringLiteral("forceFlipping"); // NOLINT(cert-err58-cpp) const QString AttrForceFlipping = QStringLiteral("forceFlipping"); // NOLINT(cert-err58-cpp)
const QString AttrSewLineOnDrawing = QStringLiteral("sewLineOnDrawing"); // NOLINT(cert-err58-cpp) const QString AttrSewLineOnDrawing = QStringLiteral("sewLineOnDrawing"); // NOLINT(cert-err58-cpp)

View file

@ -83,7 +83,8 @@ extern const QString AttrLength;
extern const QString AttrFollowGrainline; extern const QString AttrFollowGrainline;
extern const QString AttrBoundaryTogetherWithNotches; extern const QString AttrBoundaryTogetherWithNotches;
extern const QString AttrUID; extern const QString AttrUID;
extern const QString AttrMirrored; extern const QString AttrVerticallyFlipped;
extern const QString AttrHorizontallyFlipped;
extern const QString AttrForbidFlipping; extern const QString AttrForbidFlipping;
extern const QString AttrForceFlipping; extern const QString AttrForceFlipping;
extern const QString AttrSewLineOnDrawing; extern const QString AttrSewLineOnDrawing;

View file

@ -221,7 +221,8 @@
</xs:sequence> </xs:sequence>
<xs:attribute name="uid" type="uuid" use="required"/> <xs:attribute name="uid" type="uuid" use="required"/>
<xs:attribute type="xs:string" name="name"/> <xs:attribute type="xs:string" name="name"/>
<xs:attribute type="xs:boolean" name="mirrored"/> <xs:attribute type="xs:boolean" name="verticallyFlipped"/>
<xs:attribute type="xs:boolean" name="horizontallyFlipped"/>
<xs:attribute type="xs:boolean" name="forbidFlipping"/> <xs:attribute type="xs:boolean" name="forbidFlipping"/>
<xs:attribute type="xs:boolean" name="forceFlipping"/> <xs:attribute type="xs:boolean" name="forceFlipping"/>
<xs:attribute type="xs:boolean" name="followGrainline"/> <xs:attribute type="xs:boolean" name="followGrainline"/>
@ -419,7 +420,8 @@
</xs:sequence> </xs:sequence>
<xs:attribute name="uid" type="uuid" use="required"/> <xs:attribute name="uid" type="uuid" use="required"/>
<xs:attribute type="xs:string" name="name"/> <xs:attribute type="xs:string" name="name"/>
<xs:attribute type="xs:boolean" name="mirrored"/> <xs:attribute type="xs:boolean" name="verticallyFlipped"/>
<xs:attribute type="xs:boolean" name="horizontallyFlipped"/>
<xs:attribute type="xs:boolean" name="forbidFlipping"/> <xs:attribute type="xs:boolean" name="forbidFlipping"/>
<xs:attribute type="xs:boolean" name="forceFlipping"/> <xs:attribute type="xs:boolean" name="forceFlipping"/>
<xs:attribute type="xs:boolean" name="followGrainline"/> <xs:attribute type="xs:boolean" name="followGrainline"/>

View file

@ -73,6 +73,8 @@ Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrId, ("id"_L1))
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrUId, ("uid"_L1)) // NOLINT Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrUId, ("uid"_L1)) // NOLINT
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrAngle, ("angle"_L1)) // NOLINT Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrAngle, ("angle"_L1)) // NOLINT
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrArrowDirection, ("arrowDirection"_L1)) // NOLINT Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrArrowDirection, ("arrowDirection"_L1)) // NOLINT
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrMirrored, ("mirrored"_L1)) // NOLINT
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrVerticallyFlipped, ("verticallyFlipped"_L1)) // NOLINT
QT_WARNING_POP QT_WARNING_POP
@ -380,6 +382,24 @@ void VLayoutConverter::ConvertPiecesToV0_1_5()
} }
} }
//---------------------------------------------------------------------------------------------------------------------
void VLayoutConverter::ConvertPiecesToV0_1_7()
{
// TODO. Delete if minimal supported version is 0.1.7
Q_STATIC_ASSERT_X(VLayoutConverter::LayoutMinVer < FormatVersion(0, 1, 7), "Time to refactor the code.");
QDomNodeList pieceTags = elementsByTagName(*strPieceTag);
for (int i = 0; i < pieceTags.size(); ++i)
{
QDomElement node = pieceTags.at(i).toElement();
if (node.isElement() && node.hasAttribute(*strAttrMirrored))
{
node.setAttribute(*strAttrVerticallyFlipped, node.attribute(*strAttrMirrored));
node.removeAttribute(*strAttrMirrored);
}
}
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VLayoutConverter::ToV0_1_3() void VLayoutConverter::ToV0_1_3()
{ {
@ -407,6 +427,7 @@ void VLayoutConverter::ToV0_1_7()
// TODO. Delete if minimal supported version is 0.1.7 // TODO. Delete if minimal supported version is 0.1.7
Q_STATIC_ASSERT_X(VLayoutConverter::LayoutMinVer < FormatVersion(0, 1, 7), "Time to refactor the code."); Q_STATIC_ASSERT_X(VLayoutConverter::LayoutMinVer < FormatVersion(0, 1, 7), "Time to refactor the code.");
ConvertPiecesToV0_1_7();
SetVersion(QStringLiteral("0.1.7")); SetVersion(QStringLiteral("0.1.7"));
Save(); Save();
} }

View file

@ -72,6 +72,8 @@ protected:
void ConvertPiecesToV0_1_5(); void ConvertPiecesToV0_1_5();
void ConvertPiecesToV0_1_7();
void ToV0_1_3(); void ToV0_1_3();
void ToV0_1_5(); void ToV0_1_5();
void ToV0_1_7(); void ToV0_1_7();

View file

@ -162,17 +162,27 @@ inline auto LineAlign(const TextLine &tl, const QString &text, const QFontMetric
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
auto LineMatrix(const VLayoutPiece &piece, const QPointF &topLeft, qreal angle, const QPointF &linePos, auto LineMatrix(const VLayoutPiece &piece, const QPointF &topLeft, qreal angle, const QPointF &linePos,
int maxLineWidth) -> QTransform int maxLineWidth, qreal maxLabelHeight) -> QTransform
{ {
QTransform labelMatrix; QTransform labelMatrix;
labelMatrix.translate(topLeft.x(), topLeft.y()); labelMatrix.translate(topLeft.x(), topLeft.y());
if (piece.IsMirror()) if (piece.IsVerticallyFlipped() || piece.IsHorizontallyFlipped())
{
if (piece.IsVerticallyFlipped())
{ {
labelMatrix.scale(-1, 1); labelMatrix.scale(-1, 1);
labelMatrix.rotate(-angle); labelMatrix.rotate(-angle);
labelMatrix.translate(-maxLineWidth, 0); labelMatrix.translate(-maxLineWidth, 0);
} }
if (piece.IsHorizontallyFlipped())
{
labelMatrix.scale(1, -1);
labelMatrix.rotate(-angle);
labelMatrix.translate(0, -maxLabelHeight);
}
}
else else
{ {
labelMatrix.rotate(angle); labelMatrix.rotate(angle);
@ -220,6 +230,72 @@ auto NextPattern(int patternIndex, const QVector<int> &pattern) -> int
{ {
return (patternIndex + 2) % static_cast<int>(pattern.size()); return (patternIndex + 2) % static_cast<int>(pattern.size());
} }
//---------------------------------------------------------------------------------------------------------------------
auto LabelHeightSVGFont(const VLayoutPiece &detail, const QVector<TextLine> &labelLines, const VSvgFont &svgFont,
const VSvgFontDatabase *db, qreal penWidth, qreal dH, int spacing) -> qreal
{
qreal labelHeight = 0;
if (detail.IsHorizontallyFlipped())
{
for (int i = 0; i < labelLines.size(); ++i)
{
const VSvgFont fnt = LineFont(labelLines.at(i), svgFont);
VSvgFontEngine engine = db->FontEngine(fnt);
const qreal lineHeight = engine.FontHeight() + penWidth;
if (labelHeight + lineHeight > dH)
{
break;
}
if (i < labelLines.size() - 1)
{
labelHeight += lineHeight + spacing;
}
else
{
labelHeight += lineHeight;
}
}
}
return labelHeight;
}
//---------------------------------------------------------------------------------------------------------------------
auto LabelHeightOutlineFont(const VLayoutPiece &detail, const QVector<TextLine> &labelLines, const QFont &font,
qreal penWidth, qreal dH, int spacing) -> qreal
{
qreal labelHeight = 0;
if (detail.IsHorizontallyFlipped())
{
for (int i = 0; i < labelLines.size(); ++i)
{
const QFont fnt = LineFont(labelLines.at(i), font);
QFontMetrics fm(fnt);
const qreal lineHeight = fm.height() + penWidth;
if (labelHeight + lineHeight > dH)
{
break;
}
if (i < labelLines.size() - 1)
{
labelHeight += lineHeight + spacing;
}
else
{
labelHeight += lineHeight;
}
}
}
return labelHeight;
}
} // namespace } // namespace
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -475,7 +551,8 @@ void VHPGLEngine::PlotInternalPaths(QTextStream &out, const VLayoutPiece &detail
QVector<VLayoutPiecePath> internalPaths = detail.GetInternalPaths(); QVector<VLayoutPiecePath> internalPaths = detail.GetInternalPaths();
for (const auto &path : internalPaths) for (const auto &path : internalPaths)
{ {
QVector<VLayoutPoint> points = VLayoutPiece::MapVector(path.Points(), detail.GetMatrix(), detail.IsMirror()); QVector<VLayoutPoint> points = VLayoutPiece::MapVector(
path.Points(), detail.GetMatrix(), detail.IsVerticallyFlipped() || detail.IsHorizontallyFlipped());
PlotPath(out, CastToPoint(ConvertPath(points)), path.PenStyle()); PlotPath(out, CastToPoint(ConvertPath(points)), path.PenStyle());
} }
} }
@ -579,6 +656,8 @@ void VHPGLEngine::PlotLabelSVGFont(QTextStream &out, const VLayoutPiece &detail,
const QVector<TextLine> labelLines = tm.GetLabelSourceLines(qFloor(dW), svgFont, m_penWidthPx); const QVector<TextLine> labelLines = tm.GetLabelSourceLines(qFloor(dW), svgFont, m_penWidthPx);
const qreal labelHeight = LabelHeightSVGFont(detail, labelLines, svgFont, db, m_penWidthPx, dH, tm.GetSpacing());
for (const auto &tl : labelLines) for (const auto &tl : labelLines)
{ {
const VSvgFont fnt = LineFont(tl, svgFont); const VSvgFont fnt = LineFont(tl, svgFont);
@ -592,7 +671,8 @@ void VHPGLEngine::PlotLabelSVGFont(QTextStream &out, const VLayoutPiece &detail,
const QString qsText = tl.m_qsText; const QString qsText = tl.m_qsText;
const qreal dX = LineAlign(tl, qsText, engine, dW, m_penWidthPx); const qreal dX = LineAlign(tl, qsText, engine, dW, m_penWidthPx);
// set up the rotation around top-left corner matrix // set up the rotation around top-left corner matrix
const QTransform lineMatrix = LineMatrix(detail, labelShape.at(0), angle, QPointF(dX, dY), maxLineWidth); const QTransform lineMatrix =
LineMatrix(detail, labelShape.at(0), angle, QPointF(dX, dY), maxLineWidth, labelHeight);
QPainterPath path = lineMatrix.map(engine.DrawPath(QPointF(), qsText)); QPainterPath path = lineMatrix.map(engine.DrawPath(QPointF(), qsText));
PlotPainterPath(out, path, Qt::SolidLine); PlotPainterPath(out, path, Qt::SolidLine);
@ -626,6 +706,9 @@ void VHPGLEngine::PlotLabelOutlineFont(QTextStream &out, const VLayoutPiece &det
const QVector<TextLine> labelLines = tm.GetLabelSourceLines(qFloor(dW), tm.GetFont()); const QVector<TextLine> labelLines = tm.GetLabelSourceLines(qFloor(dW), tm.GetFont());
const qreal labelHeight =
LabelHeightOutlineFont(detail, labelLines, tm.GetFont(), m_penWidthPx, dH, tm.GetSpacing());
for (const auto &tl : labelLines) for (const auto &tl : labelLines)
{ {
const QFont fnt = LineFont(tl, tm.GetFont()); const QFont fnt = LineFont(tl, tm.GetFont());
@ -646,7 +729,8 @@ void VHPGLEngine::PlotLabelOutlineFont(QTextStream &out, const VLayoutPiece &det
const QString qsText = tl.m_qsText; const QString qsText = tl.m_qsText;
const qreal dX = LineAlign(tl, qsText, fm, dW); const qreal dX = LineAlign(tl, qsText, fm, dW);
// set up the rotation around top-left corner matrix // set up the rotation around top-left corner matrix
const QTransform lineMatrix = LineMatrix(detail, labelShape.at(0), angle, QPointF(dX, dY), maxLineWidth); const QTransform lineMatrix =
LineMatrix(detail, labelShape.at(0), angle, QPointF(dX, dY), maxLineWidth, labelHeight);
QPainterPath path; QPainterPath path;

View file

@ -284,7 +284,7 @@ auto VLayoutPaper::SaveResult(const VBestSquare &bestResult, const VLayoutPiece
{ {
VLayoutPiece workDetail = detail; VLayoutPiece workDetail = detail;
workDetail.SetMatrix(bestResult.Matrix()); // Don't forget set matrix workDetail.SetMatrix(bestResult.Matrix()); // Don't forget set matrix
workDetail.SetMirror(bestResult.Mirror()); workDetail.SetVerticallyFlipped(bestResult.Mirror());
if (d->saveLength) if (d->saveLength)
{ {

View file

@ -667,7 +667,7 @@ template <> auto VLayoutPiece::Map<VLayoutPoint>(QVector<VLayoutPoint> points) c
point.ry() = p.y(); point.ry() = p.y();
return point; return point;
}); });
if (d->m_mirror) if (d->m_verticallyFlipped || d->m_horizontallyFlipped)
{ {
std::reverse(points.begin(), points.end()); std::reverse(points.begin(), points.end());
} }
@ -1087,7 +1087,7 @@ void VLayoutPiece::Mirror(const QLineF &edge)
m.translate(-p2.x(), -p2.y()); m.translate(-p2.x(), -p2.y());
d->m_matrix *= m; d->m_matrix *= m;
d->m_mirror = !d->m_mirror; d->m_verticallyFlipped = !d->m_verticallyFlipped;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -1096,7 +1096,7 @@ void VLayoutPiece::Mirror()
QTransform m; QTransform m;
m.scale(-1, 1); m.scale(-1, 1);
d->m_matrix *= m; d->m_matrix *= m;
d->m_mirror = !d->m_mirror; d->m_verticallyFlipped = !d->m_verticallyFlipped;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -1607,7 +1607,7 @@ void VLayoutPiece::LabelStringsSVGFont(QGraphicsItem *parent, const QVector<QPoi
// set up the rotation around top-left corner matrix // set up the rotation around top-left corner matrix
QTransform labelMatrix; QTransform labelMatrix;
labelMatrix.translate(labelShape.at(0).x(), labelShape.at(0).y()); labelMatrix.translate(labelShape.at(0).x(), labelShape.at(0).y());
if (d->m_mirror) if (d->m_verticallyFlipped)
{ {
labelMatrix.scale(-1, 1); labelMatrix.scale(-1, 1);
labelMatrix.rotate(-angle); labelMatrix.rotate(-angle);
@ -1704,7 +1704,7 @@ void VLayoutPiece::LabelStringsOutlineFont(QGraphicsItem *parent, const QVector<
// set up the rotation around top-left corner matrix // set up the rotation around top-left corner matrix
QTransform labelMatrix; QTransform labelMatrix;
labelMatrix.translate(labelShape.at(0).x(), labelShape.at(0).y()); labelMatrix.translate(labelShape.at(0).x(), labelShape.at(0).y());
if (d->m_mirror) if (d->m_verticallyFlipped)
{ {
labelMatrix.scale(-1, 1); labelMatrix.scale(-1, 1);
labelMatrix.rotate(-angle); labelMatrix.rotate(-angle);
@ -1844,15 +1844,27 @@ auto VLayoutPiece::GetMainPathItem() const -> QGraphicsPathItem *
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::IsMirror() const -> bool auto VLayoutPiece::IsVerticallyFlipped() const -> bool
{ {
return d->m_mirror; return d->m_verticallyFlipped;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::SetMirror(bool value) void VLayoutPiece::SetVerticallyFlipped(bool value)
{ {
d->m_mirror = value; d->m_verticallyFlipped = value;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::IsHorizontallyFlipped() const -> bool
{
return d->m_horizontallyFlipped;
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::SetHorizontallyFlipped(bool value)
{
d->m_horizontallyFlipped = value;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -1911,7 +1923,7 @@ auto VLayoutPiece::Edge(const QVector<QPointF> &path, int i) const -> QLineF
i2 = 0; i2 = 0;
} }
if (d->m_mirror) if (d->m_verticallyFlipped || d->m_horizontallyFlipped)
{ {
QVector<QPointF> newPath = Map(path); QVector<QPointF> newPath = Map(path);
return {newPath.at(i1), newPath.at(i2)}; return {newPath.at(i1), newPath.at(i2)};
@ -1940,7 +1952,7 @@ auto VLayoutPiece::EdgeByPoint(const QVector<QPointF> &path, const QPointF &p1)
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
template <class T> auto VLayoutPiece::Map(QVector<T> points) const -> QVector<T> template <class T> auto VLayoutPiece::Map(QVector<T> points) const -> QVector<T>
{ {
return MapVector(points, d->m_matrix, d->m_mirror); return MapVector(points, d->m_matrix, d->m_verticallyFlipped || d->m_horizontallyFlipped);
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------

View file

@ -156,8 +156,11 @@ public:
auto GetId() const -> vidtype; auto GetId() const -> vidtype;
void SetId(vidtype id); void SetId(vidtype id);
auto IsMirror() const -> bool; auto IsVerticallyFlipped() const -> bool;
void SetMirror(bool value); void SetVerticallyFlipped(bool value);
auto IsHorizontallyFlipped() const -> bool;
void SetHorizontallyFlipped(bool value);
void SetGradationId(const QString &id); void SetGradationId(const QString &id);
auto GetGradationId() const -> QString; auto GetGradationId() const -> QString;

View file

@ -83,7 +83,8 @@ public:
/** @brief layoutWidth value layout allowance width in pixels. */ /** @brief layoutWidth value layout allowance width in pixels. */
qreal m_layoutWidth{0}; // NOLINT(misc-non-private-member-variables-in-classes) qreal m_layoutWidth{0}; // NOLINT(misc-non-private-member-variables-in-classes)
bool m_mirror{false}; // NOLINT(misc-non-private-member-variables-in-classes) bool m_verticallyFlipped{false}; // NOLINT(misc-non-private-member-variables-in-classes)
bool m_horizontallyFlipped{false}; // NOLINT(misc-non-private-member-variables-in-classes)
/** @brief detailLabel detail label rectangle */ /** @brief detailLabel detail label rectangle */
QVector<QPointF> m_detailLabel{}; // NOLINT(misc-non-private-member-variables-in-classes) QVector<QPointF> m_detailLabel{}; // NOLINT(misc-non-private-member-variables-in-classes)
@ -118,7 +119,7 @@ private:
Q_DISABLE_ASSIGN_MOVE(VLayoutPieceData) // NOLINT Q_DISABLE_ASSIGN_MOVE(VLayoutPieceData) // NOLINT
static constexpr quint32 streamHeader{0x80D7D009}; // CRC-32Q string "VLayoutPieceData" static constexpr quint32 streamHeader{0x80D7D009}; // CRC-32Q string "VLayoutPieceData"
static constexpr quint16 classVersion{5}; static constexpr quint16 classVersion{6};
}; };
QT_WARNING_POP QT_WARNING_POP
@ -142,7 +143,7 @@ inline auto operator<<(QDataStream &dataStream, const VLayoutPieceData &piece) -
dataStream << piece.m_internalPaths; dataStream << piece.m_internalPaths;
dataStream << piece.m_matrix; dataStream << piece.m_matrix;
dataStream << piece.m_layoutWidth; dataStream << piece.m_layoutWidth;
dataStream << piece.m_mirror; dataStream << piece.m_verticallyFlipped;
dataStream << piece.m_detailLabel; dataStream << piece.m_detailLabel;
dataStream << piece.m_patternInfo; dataStream << piece.m_patternInfo;
dataStream << piece.m_placeLabels; dataStream << piece.m_placeLabels;
@ -155,6 +156,7 @@ inline auto operator<<(QDataStream &dataStream, const VLayoutPieceData &piece) -
dataStream << piece.m_xScale; dataStream << piece.m_xScale;
dataStream << piece.m_yScale; dataStream << piece.m_yScale;
dataStream << piece.m_grainline; dataStream << piece.m_grainline;
dataStream << piece.m_horizontallyFlipped;
return dataStream; return dataStream;
} }
@ -211,7 +213,7 @@ inline auto operator>>(QDataStream &dataStream, VLayoutPieceData &piece) -> QDat
dataStream >> piece.m_internalPaths; dataStream >> piece.m_internalPaths;
dataStream >> piece.m_matrix; dataStream >> piece.m_matrix;
dataStream >> piece.m_layoutWidth; dataStream >> piece.m_layoutWidth;
dataStream >> piece.m_mirror; dataStream >> piece.m_verticallyFlipped;
dataStream >> piece.m_detailLabel; dataStream >> piece.m_detailLabel;
dataStream >> piece.m_patternInfo; dataStream >> piece.m_patternInfo;
@ -268,6 +270,11 @@ inline auto operator>>(QDataStream &dataStream, VLayoutPieceData &piece) -> QDat
} }
} }
if (actualClassVersion >= 6)
{
dataStream >> piece.m_horizontallyFlipped;
}
return dataStream; return dataStream;
} }

View file

@ -281,7 +281,7 @@ void VPosition::SaveCandidate(VBestSquare &bestResult, const VLayoutPiece &detai
data.globalI = globalI; // Edge of global contour data.globalI = globalI; // Edge of global contour
data.detJ = detJ; // Edge of detail data.detJ = detJ; // Edge of detail
data.resMatrix = detail.GetMatrix(); // Matrix for rotation and translation detail data.resMatrix = detail.GetMatrix(); // Matrix for rotation and translation detail
data.resMirror = detail.IsMirror(); data.resMirror = detail.IsVerticallyFlipped();
data.type = type; data.type = type;
data.depthPosition = depthPosition; data.depthPosition = depthPosition;
data.sidePosition = sidePosition; data.sidePosition = sidePosition;