Horizontal piece flipping.
This commit is contained in:
parent
a7073dbeae
commit
e9565b3e75
|
@ -59,6 +59,7 @@
|
|||
- New tools: Arc start point, Arc end point.
|
||||
- Optimize U-notch shape.
|
||||
- New feature. Boundary together with notches.
|
||||
- Puzzle app. Horizontal piece flipping.
|
||||
|
||||
# Valentina 0.7.52 September 12, 2022
|
||||
- Fix crash when default locale is ru.
|
||||
|
|
|
@ -144,7 +144,7 @@ VPPiece::VPPiece(const VLayoutPiece &layoutPiece)
|
|||
|
||||
if (IsForceFlipping())
|
||||
{
|
||||
Flip();
|
||||
FlipVertically();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,8 @@ void VPPiece::ClearTransformations()
|
|||
const QPointF offset = MappedDetailBoundingRect().topLeft();
|
||||
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();
|
||||
QPointF center = pieceMatrix.map(DetailBoundingRect().center());
|
||||
|
@ -299,7 +300,23 @@ void VPPiece::Flip()
|
|||
|
||||
pieceMatrix *= m;
|
||||
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());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -97,9 +97,10 @@ public:
|
|||
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;
|
||||
void SetOutOfBound(bool newOutOfBound);
|
||||
|
|
|
@ -72,7 +72,7 @@ namespace
|
|||
{
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
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())
|
||||
{
|
||||
|
@ -82,11 +82,21 @@ inline auto LineMatrix(const VPPiecePtr &piece, const QPointF &topLeft, qreal an
|
|||
QTransform labelMatrix;
|
||||
labelMatrix.translate(topLeft.x(), topLeft.y());
|
||||
|
||||
if (piece->IsMirror())
|
||||
if (piece->IsVerticallyFlipped() || piece->IsHorizontallyFlipped())
|
||||
{
|
||||
labelMatrix.scale(-1, 1);
|
||||
labelMatrix.rotate(-angle);
|
||||
labelMatrix.translate(-maxLineWidth, 0);
|
||||
if (piece->IsVerticallyFlipped())
|
||||
{
|
||||
labelMatrix.scale(-1, 1);
|
||||
labelMatrix.rotate(-angle);
|
||||
labelMatrix.translate(-maxLineWidth, 0);
|
||||
}
|
||||
|
||||
if (piece->IsHorizontallyFlipped())
|
||||
{
|
||||
labelMatrix.scale(1, -1);
|
||||
labelMatrix.rotate(-angle);
|
||||
labelMatrix.translate(0, -maxLabelHeight);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -169,6 +179,72 @@ inline auto SelectionBrush() -> QBrush
|
|||
{
|
||||
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
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -441,6 +517,8 @@ void VPGraphicsPiece::InitPieceLabelSVGFont(const QVector<QPointF> &labelShape,
|
|||
|
||||
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)
|
||||
{
|
||||
const VSvgFont fnt = LineFont(tl, svgFont);
|
||||
|
@ -454,7 +532,8 @@ void VPGraphicsPiece::InitPieceLabelSVGFont(const QVector<QPointF> &labelShape,
|
|||
const QString qsText = tl.m_qsText;
|
||||
const qreal dX = LineAlign(tl, qsText, engine, dW, penWidth);
|
||||
// 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);
|
||||
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 qreal labelHeight =
|
||||
LabelHeightOutlineFont(piece, labelLines, tm.GetFont(), textAsPaths, penWidth, dH, tm.GetSpacing());
|
||||
|
||||
for (const auto &tl : labelLines)
|
||||
{
|
||||
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 qreal dX = LineAlign(tl, qsText, fm, dW);
|
||||
// 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)
|
||||
{
|
||||
|
|
|
@ -782,7 +782,7 @@ void VPMainWindow::InitPropertyTabCurrentPiece()
|
|||
}
|
||||
});
|
||||
|
||||
connect(ui->checkBoxCurrentPieceMirrorPiece, &QCheckBox::toggled, this,
|
||||
connect(ui->checkBoxCurrentPieceVerticallyFlipped, &QCheckBox::toggled, this,
|
||||
[this](bool checked)
|
||||
{
|
||||
QList<VPPiecePtr> selectedPieces = SelectedPieces();
|
||||
|
@ -791,9 +791,28 @@ void VPMainWindow::InitPropertyTabCurrentPiece()
|
|||
const VPPiecePtr &selectedPiece = selectedPieces.constFirst();
|
||||
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);
|
||||
emit m_layout->PieceTransformationChanged(selectedPiece);
|
||||
}
|
||||
|
@ -1287,10 +1306,11 @@ void VPMainWindow::SetPropertyTabCurrentPieceData()
|
|||
SetLineEditValue(ui->lineEditCurrentPieceGradationId, selectedPiece->GetGradationId());
|
||||
|
||||
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();
|
||||
ui->checkBoxCurrentPieceMirrorPiece->setDisabled(disableFlipping);
|
||||
ui->checkBoxCurrentPieceVerticallyFlipped->setDisabled(disableFlipping);
|
||||
|
||||
if (not ui->checkBoxRelativeTranslation->isChecked())
|
||||
{
|
||||
|
|
|
@ -279,8 +279,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>392</width>
|
||||
<height>700</height>
|
||||
<width>378</width>
|
||||
<height>707</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_23">
|
||||
|
@ -624,9 +624,16 @@
|
|||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxCurrentPieceMirrorPiece">
|
||||
<widget class="QCheckBox" name="checkBoxCurrentPieceVerticallyFlipped">
|
||||
<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>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -2416,7 +2423,7 @@
|
|||
<tabstop>lineEditCurrentPieceName</tabstop>
|
||||
<tabstop>plainTextEditCurrentPieceUUID</tabstop>
|
||||
<tabstop>checkBoxCurrentPieceShowSeamline</tabstop>
|
||||
<tabstop>checkBoxCurrentPieceMirrorPiece</tabstop>
|
||||
<tabstop>checkBoxCurrentPieceVerticallyFlipped</tabstop>
|
||||
<tabstop>doubleSpinBoxCurrentPieceAngle</tabstop>
|
||||
<tabstop>doubleSpinBoxCurrentPieceBoxPositionX</tabstop>
|
||||
<tabstop>doubleSpinBoxCurrentPieceBoxPositionY</tabstop>
|
||||
|
@ -2434,8 +2441,8 @@
|
|||
</resources>
|
||||
<connections/>
|
||||
<buttongroups>
|
||||
<buttongroup name="buttonGroupTileOrientation"/>
|
||||
<buttongroup name="buttonGroupSheetOrientation"/>
|
||||
<buttongroup name="buttonGroupRotationDirection"/>
|
||||
<buttongroup name="buttonGroupSheetOrientation"/>
|
||||
<buttongroup name="buttonGroupTileOrientation"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
|
|
|
@ -511,7 +511,8 @@ void VPLayoutFileReader::ReadPiece(const VPPiecePtr &piece)
|
|||
piece->SetXScale(ReadAttributeDouble(attribs, ML::AttrXScale, QChar('1')));
|
||||
piece->SetYScale(ReadAttributeDouble(attribs, ML::AttrYScale, 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->SetForceFlipping(ReadAttributeBool(attribs, ML::AttrForceFlipping, falseStr));
|
||||
piece->SetFollowGrainline(ReadAttributeBool(attribs, ML::AttrFollowGrainline, falseStr));
|
||||
|
|
|
@ -260,8 +260,10 @@ void VPLayoutFileWriter::WritePiece(const VPPiecePtr &piece)
|
|||
writeStartElement(ML::TagPiece);
|
||||
SetAttribute(ML::AttrUID, piece->GetUUID().toString());
|
||||
SetAttribute(ML::AttrName, piece->GetName());
|
||||
SetAttributeOrRemoveIf<bool>(ML::AttrMirrored, piece->IsMirror(),
|
||||
[](bool mirrored) noexcept { return not mirrored; });
|
||||
SetAttributeOrRemoveIf<bool>(ML::AttrVerticallyFlipped, piece->IsVerticallyFlipped(),
|
||||
[](bool flipped) noexcept { return not flipped; });
|
||||
SetAttributeOrRemoveIf<bool>(ML::AttrHorizontallyFlipped, piece->IsHorizontallyFlipped(),
|
||||
[](bool flipped) noexcept { return not flipped; });
|
||||
SetAttributeOrRemoveIf<bool>(ML::AttrForbidFlipping, piece->IsForbidFlipping(),
|
||||
[](bool forbid) noexcept { return not forbid; });
|
||||
SetAttributeOrRemoveIf<bool>(ML::AttrForceFlipping, piece->IsForceFlipping(),
|
||||
|
|
|
@ -84,7 +84,8 @@ const QString AttrLength = QStringLiteral("length");
|
|||
const QString AttrFollowGrainline = QStringLiteral("followGrainline"); // NOLINT(cert-err58-cpp)
|
||||
const QString AttrBoundaryTogetherWithNotches = QStringLiteral("boundaryTogetherWithNotches"); // 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 AttrForceFlipping = QStringLiteral("forceFlipping"); // NOLINT(cert-err58-cpp)
|
||||
const QString AttrSewLineOnDrawing = QStringLiteral("sewLineOnDrawing"); // NOLINT(cert-err58-cpp)
|
||||
|
|
|
@ -83,7 +83,8 @@ extern const QString AttrLength;
|
|||
extern const QString AttrFollowGrainline;
|
||||
extern const QString AttrBoundaryTogetherWithNotches;
|
||||
extern const QString AttrUID;
|
||||
extern const QString AttrMirrored;
|
||||
extern const QString AttrVerticallyFlipped;
|
||||
extern const QString AttrHorizontallyFlipped;
|
||||
extern const QString AttrForbidFlipping;
|
||||
extern const QString AttrForceFlipping;
|
||||
extern const QString AttrSewLineOnDrawing;
|
||||
|
|
|
@ -221,7 +221,8 @@
|
|||
</xs:sequence>
|
||||
<xs:attribute name="uid" type="uuid" use="required"/>
|
||||
<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="forceFlipping"/>
|
||||
<xs:attribute type="xs:boolean" name="followGrainline"/>
|
||||
|
@ -419,7 +420,8 @@
|
|||
</xs:sequence>
|
||||
<xs:attribute name="uid" type="uuid" use="required"/>
|
||||
<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="forceFlipping"/>
|
||||
<xs:attribute type="xs:boolean" name="followGrainline"/>
|
||||
|
|
|
@ -58,21 +58,23 @@ QT_WARNING_DISABLE_CLANG("-Wunused-member-function")
|
|||
|
||||
// The list of all string we use for conversion
|
||||
// Better to use global variables because repeating QStringLiteral blows up code size
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strSeamLineTag, ("seamLine"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strSeamAllowanceTag, ("seamAllowance"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strInternalPathTag, ("internalPath"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strMarkerTag, ("marker"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strPointTag, ("point"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strPieceTag, ("piece"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strGrainlineTag, ("grainline"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrX, ("x"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrY, ("y"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrTurnPoint, ("turnPoint"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrCurvePoint, ("curvePoint"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrId, ("id"_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, strAttrArrowDirection, ("arrowDirection"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strSeamLineTag, ("seamLine"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strSeamAllowanceTag, ("seamAllowance"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strInternalPathTag, ("internalPath"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strMarkerTag, ("marker"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strPointTag, ("point"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strPieceTag, ("piece"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strGrainlineTag, ("grainline"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrX, ("x"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrY, ("y"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrTurnPoint, ("turnPoint"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrCurvePoint, ("curvePoint"_L1)) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrId, ("id"_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, 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
|
||||
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -407,6 +427,7 @@ void VLayoutConverter::ToV0_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.");
|
||||
|
||||
ConvertPiecesToV0_1_7();
|
||||
SetVersion(QStringLiteral("0.1.7"));
|
||||
Save();
|
||||
}
|
||||
|
|
|
@ -72,6 +72,8 @@ protected:
|
|||
|
||||
void ConvertPiecesToV0_1_5();
|
||||
|
||||
void ConvertPiecesToV0_1_7();
|
||||
|
||||
void ToV0_1_3();
|
||||
void ToV0_1_5();
|
||||
void ToV0_1_7();
|
||||
|
|
|
@ -162,16 +162,26 @@ inline auto LineAlign(const TextLine &tl, const QString &text, const QFontMetric
|
|||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto LineMatrix(const VLayoutPiece &piece, const QPointF &topLeft, qreal angle, const QPointF &linePos,
|
||||
int maxLineWidth) -> QTransform
|
||||
int maxLineWidth, qreal maxLabelHeight) -> QTransform
|
||||
{
|
||||
QTransform labelMatrix;
|
||||
labelMatrix.translate(topLeft.x(), topLeft.y());
|
||||
|
||||
if (piece.IsMirror())
|
||||
if (piece.IsVerticallyFlipped() || piece.IsHorizontallyFlipped())
|
||||
{
|
||||
labelMatrix.scale(-1, 1);
|
||||
labelMatrix.rotate(-angle);
|
||||
labelMatrix.translate(-maxLineWidth, 0);
|
||||
if (piece.IsVerticallyFlipped())
|
||||
{
|
||||
labelMatrix.scale(-1, 1);
|
||||
labelMatrix.rotate(-angle);
|
||||
labelMatrix.translate(-maxLineWidth, 0);
|
||||
}
|
||||
|
||||
if (piece.IsHorizontallyFlipped())
|
||||
{
|
||||
labelMatrix.scale(1, -1);
|
||||
labelMatrix.rotate(-angle);
|
||||
labelMatrix.translate(0, -maxLabelHeight);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -220,6 +230,72 @@ auto NextPattern(int patternIndex, const QVector<int> &pattern) -> int
|
|||
{
|
||||
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
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -475,7 +551,8 @@ void VHPGLEngine::PlotInternalPaths(QTextStream &out, const VLayoutPiece &detail
|
|||
QVector<VLayoutPiecePath> internalPaths = detail.GetInternalPaths();
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
@ -579,6 +656,8 @@ void VHPGLEngine::PlotLabelSVGFont(QTextStream &out, const VLayoutPiece &detail,
|
|||
|
||||
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)
|
||||
{
|
||||
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 qreal dX = LineAlign(tl, qsText, engine, dW, m_penWidthPx);
|
||||
// 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));
|
||||
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 qreal labelHeight =
|
||||
LabelHeightOutlineFont(detail, labelLines, tm.GetFont(), m_penWidthPx, dH, tm.GetSpacing());
|
||||
|
||||
for (const auto &tl : labelLines)
|
||||
{
|
||||
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 qreal dX = LineAlign(tl, qsText, fm, dW);
|
||||
// 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;
|
||||
|
||||
|
|
|
@ -284,7 +284,7 @@ auto VLayoutPaper::SaveResult(const VBestSquare &bestResult, const VLayoutPiece
|
|||
{
|
||||
VLayoutPiece workDetail = detail;
|
||||
workDetail.SetMatrix(bestResult.Matrix()); // Don't forget set matrix
|
||||
workDetail.SetMirror(bestResult.Mirror());
|
||||
workDetail.SetVerticallyFlipped(bestResult.Mirror());
|
||||
|
||||
if (d->saveLength)
|
||||
{
|
||||
|
|
|
@ -667,7 +667,7 @@ template <> auto VLayoutPiece::Map<VLayoutPoint>(QVector<VLayoutPoint> points) c
|
|||
point.ry() = p.y();
|
||||
return point;
|
||||
});
|
||||
if (d->m_mirror)
|
||||
if (d->m_verticallyFlipped || d->m_horizontallyFlipped)
|
||||
{
|
||||
std::reverse(points.begin(), points.end());
|
||||
}
|
||||
|
@ -1087,7 +1087,7 @@ void VLayoutPiece::Mirror(const QLineF &edge)
|
|||
m.translate(-p2.x(), -p2.y());
|
||||
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;
|
||||
m.scale(-1, 1);
|
||||
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
|
||||
QTransform labelMatrix;
|
||||
labelMatrix.translate(labelShape.at(0).x(), labelShape.at(0).y());
|
||||
if (d->m_mirror)
|
||||
if (d->m_verticallyFlipped)
|
||||
{
|
||||
labelMatrix.scale(-1, 1);
|
||||
labelMatrix.rotate(-angle);
|
||||
|
@ -1704,7 +1704,7 @@ void VLayoutPiece::LabelStringsOutlineFont(QGraphicsItem *parent, const QVector<
|
|||
// set up the rotation around top-left corner matrix
|
||||
QTransform labelMatrix;
|
||||
labelMatrix.translate(labelShape.at(0).x(), labelShape.at(0).y());
|
||||
if (d->m_mirror)
|
||||
if (d->m_verticallyFlipped)
|
||||
{
|
||||
labelMatrix.scale(-1, 1);
|
||||
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;
|
||||
}
|
||||
|
||||
if (d->m_mirror)
|
||||
if (d->m_verticallyFlipped || d->m_horizontallyFlipped)
|
||||
{
|
||||
QVector<QPointF> newPath = Map(path);
|
||||
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>
|
||||
{
|
||||
return MapVector(points, d->m_matrix, d->m_mirror);
|
||||
return MapVector(points, d->m_matrix, d->m_verticallyFlipped || d->m_horizontallyFlipped);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -156,8 +156,11 @@ public:
|
|||
auto GetId() const -> vidtype;
|
||||
void SetId(vidtype id);
|
||||
|
||||
auto IsMirror() const -> bool;
|
||||
void SetMirror(bool value);
|
||||
auto IsVerticallyFlipped() const -> bool;
|
||||
void SetVerticallyFlipped(bool value);
|
||||
|
||||
auto IsHorizontallyFlipped() const -> bool;
|
||||
void SetHorizontallyFlipped(bool value);
|
||||
|
||||
void SetGradationId(const QString &id);
|
||||
auto GetGradationId() const -> QString;
|
||||
|
|
|
@ -83,7 +83,8 @@ public:
|
|||
/** @brief layoutWidth value layout allowance width in pixels. */
|
||||
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 */
|
||||
QVector<QPointF> m_detailLabel{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
|
@ -118,7 +119,7 @@ private:
|
|||
Q_DISABLE_ASSIGN_MOVE(VLayoutPieceData) // NOLINT
|
||||
|
||||
static constexpr quint32 streamHeader{0x80D7D009}; // CRC-32Q string "VLayoutPieceData"
|
||||
static constexpr quint16 classVersion{5};
|
||||
static constexpr quint16 classVersion{6};
|
||||
};
|
||||
|
||||
QT_WARNING_POP
|
||||
|
@ -142,7 +143,7 @@ inline auto operator<<(QDataStream &dataStream, const VLayoutPieceData &piece) -
|
|||
dataStream << piece.m_internalPaths;
|
||||
dataStream << piece.m_matrix;
|
||||
dataStream << piece.m_layoutWidth;
|
||||
dataStream << piece.m_mirror;
|
||||
dataStream << piece.m_verticallyFlipped;
|
||||
dataStream << piece.m_detailLabel;
|
||||
dataStream << piece.m_patternInfo;
|
||||
dataStream << piece.m_placeLabels;
|
||||
|
@ -155,6 +156,7 @@ inline auto operator<<(QDataStream &dataStream, const VLayoutPieceData &piece) -
|
|||
dataStream << piece.m_xScale;
|
||||
dataStream << piece.m_yScale;
|
||||
dataStream << piece.m_grainline;
|
||||
dataStream << piece.m_horizontallyFlipped;
|
||||
|
||||
return dataStream;
|
||||
}
|
||||
|
@ -211,7 +213,7 @@ inline auto operator>>(QDataStream &dataStream, VLayoutPieceData &piece) -> QDat
|
|||
dataStream >> piece.m_internalPaths;
|
||||
dataStream >> piece.m_matrix;
|
||||
dataStream >> piece.m_layoutWidth;
|
||||
dataStream >> piece.m_mirror;
|
||||
dataStream >> piece.m_verticallyFlipped;
|
||||
dataStream >> piece.m_detailLabel;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -281,7 +281,7 @@ void VPosition::SaveCandidate(VBestSquare &bestResult, const VLayoutPiece &detai
|
|||
data.globalI = globalI; // Edge of global contour
|
||||
data.detJ = detJ; // Edge of detail
|
||||
data.resMatrix = detail.GetMatrix(); // Matrix for rotation and translation detail
|
||||
data.resMirror = detail.IsMirror();
|
||||
data.resMirror = detail.IsVerticallyFlipped();
|
||||
data.type = type;
|
||||
data.depthPosition = depthPosition;
|
||||
data.sidePosition = sidePosition;
|
||||
|
|
Loading…
Reference in New Issue
Block a user