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.
- 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.

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())
{
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());
}
//---------------------------------------------------------------------------------------------------------------------

View file

@ -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);

View file

@ -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)
{

View file

@ -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())
{

View file

@ -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>

View file

@ -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));

View file

@ -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(),

View file

@ -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)

View file

@ -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;

View file

@ -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"/>

View file

@ -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();
}

View file

@ -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();

View file

@ -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;

View file

@ -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)
{

View file

@ -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);
}
//---------------------------------------------------------------------------------------------------------------------

View file

@ -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;

View file

@ -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;
}

View file

@ -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;