New features: Mirror line, Fold line.

This commit is contained in:
Roman Telezhynskyi 2024-01-06 14:20:56 +02:00
parent 670f08eb9b
commit 38fbc03f16
161 changed files with 30865 additions and 16436 deletions

View File

@ -60,6 +60,8 @@
- Optimize U-notch shape.
- New feature. Boundary together with notches.
- Puzzle app. Horizontal piece flipping.
- Mirror line.
- Fold line.
# 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

@ -404,3 +404,15 @@ auto VPLayoutSettings::IsBoundaryTogetherWithNotches() const -> bool
{
return m_togetherWithNotches;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetCutOnFold(bool value)
{
m_cutOnFold = value;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::IsCutOnFold() const -> bool
{
return m_cutOnFold;
}

View File

@ -322,6 +322,9 @@ public:
void SetBoundaryTogetherWithNotches(bool value);
auto IsBoundaryTogetherWithNotches() const -> bool;
void SetCutOnFold(bool value);
auto IsCutOnFold() const -> bool;
private:
Unit m_unit{Unit::Cm};
@ -382,6 +385,7 @@ private:
bool m_showTileNumbers{false};
bool m_togetherWithNotches{false};
bool m_cutOnFold{false};
};
#endif // VPLAYOUTSETTINGS_H

View File

@ -32,12 +32,12 @@
#include "../vgeometry/vlayoutplacelabel.h"
#include "../vlayout/vlayoutpiecepath.h"
#include "../vlayout/vtextmanager.h"
#include "qline.h"
#include "vpiecegrainline.h"
#include "../vwidgets/vpiecegrainline.h"
#include "vplayout.h"
#include "vpsheet.h"
#include <QIcon>
#include <QLine>
#include <QLoggingCategory>
#include <QPainter>
#include <QPainterPath>
@ -123,7 +123,7 @@ auto ClosestDistance(const QVector<QPointF> &path1, const QVector<QPointF> &path
{
for (auto p2 : path2)
{
QLineF d(p1, p2);
QLineF const d(p1, p2);
if (d.length() <= distance)
{
distance = d.length();
@ -141,11 +141,6 @@ VPPiece::VPPiece(const VLayoutPiece &layoutPiece)
: VLayoutPiece(layoutPiece)
{
ClearTransformations();
if (IsForceFlipping())
{
FlipVertically();
}
}
//---------------------------------------------------------------------------------------------------------------------
@ -167,6 +162,18 @@ void VPPiece::Update(const VPPiecePtr &piece)
SetPieceLabelData(piece->GetPieceLabelData());
SetPatternLabelRect(piece->GetPatternLabelRect());
SetPatternLabelData(piece->GetPatternLabelData());
SetSeamMirrorLine(piece->GetSeamMirrorLine());
SetSeamAllowanceMirrorLine(piece->GetMappedSeamAllowanceMirrorLine());
SetFoldLineLabel(piece->GetFoldLineLabel());
SetFoldLineLabelAlignment(piece->GetFoldLineLabelAlignment());
SetFoldLineType(piece->GetFoldLineType());
SetFoldLineSvgFontSize(piece->GetFoldLineSvgFontSize());
SetFoldLineLabelFontItalic(piece->IsFoldLineLabelFontItalic());
SetFoldLineLabelFontBold(piece->IsFoldLineLabelFontBold());
SetFoldLineOutlineFont(piece->GetFoldLineOutlineFont());
SetFoldLineSVGFontFamily(piece->GetFoldLineSVGFontFamily());
SetFoldLineHeight(piece->GetFoldLineHeight());
SetFoldLineWidth(piece->GetFoldLineWidth());
}
//---------------------------------------------------------------------------------------------------------------------
@ -202,6 +209,11 @@ void VPPiece::ClearTransformations()
SetVerticallyFlipped(false);
SetHorizontallyFlipped(false);
if (IsForceFlipping())
{
FlipVertically();
}
}
//---------------------------------------------------------------------------------------------------------------------
@ -291,7 +303,7 @@ void VPPiece::SetGrainline(const VPieceGrainline &grainline)
void VPPiece::FlipVertically()
{
QTransform pieceMatrix = GetMatrix();
QPointF center = pieceMatrix.map(DetailBoundingRect().center());
QPointF const center = pieceMatrix.map(DetailBoundingRect().center());
QTransform m;
m.translate(center.x(), 0);
@ -307,7 +319,7 @@ void VPPiece::FlipVertically()
void VPPiece::FlipHorizontally()
{
QTransform pieceMatrix = GetMatrix();
QPointF center = pieceMatrix.map(DetailBoundingRect().center());
QPointF const center = pieceMatrix.map(DetailBoundingRect().center());
QTransform m;
m.translate(0, center.y());
@ -322,85 +334,52 @@ void VPPiece::FlipHorizontally()
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::StickyPosition(qreal &dx, qreal &dy) const -> bool
{
VPLayoutPtr layout = Layout();
VPLayoutPtr const layout = Layout();
if (layout.isNull() || not layout->LayoutSettings().GetStickyEdges())
{
return false;
}
const qreal pieceGap = layout->LayoutSettings().GetPiecesGap();
if (pieceGap <= 0)
{
return false;
}
VPSheetPtr sheet = Sheet();
VPSheetPtr const sheet = Sheet();
if (sheet.isNull())
{
return false;
}
QList<VPPiecePtr> allPieces = sheet->GetPieces();
VStickyDistance match;
if (allPieces.count() < 2)
if (!StickySheet(match))
{
return false;
}
QVector<QPointF> path;
CastTo(GetMappedExternalContourPoints(), path);
QRectF boundingRect = VLayoutPiece::BoundingRect(path);
const qreal stickyDistance = pieceGap + minStickyDistance;
QRectF stickyZone = QRectF(boundingRect.topLeft().x() - stickyDistance, boundingRect.topLeft().y() - stickyDistance,
boundingRect.width() + stickyDistance * 2, boundingRect.height() + stickyDistance * 2);
QVector<QPointF> stickyPath = PrepareStickyPath(path);
QLineF closestDistance;
for (const auto &piece : allPieces)
{
if (piece.isNull() || piece->GetUniqueID() == GetUniqueID())
{
continue;
}
QVector<QPointF> piecePath;
CastTo(piece->GetMappedExternalContourPoints(), piecePath);
QRectF pieceBoundingRect = VLayoutPiece::BoundingRect(piecePath);
if (stickyZone.intersects(pieceBoundingRect) || pieceBoundingRect.contains(stickyZone) ||
stickyZone.contains(pieceBoundingRect))
{
if (not VPPiece::PathsSuperposition(path, piecePath))
{
QVector<QPointF> pieceStickyPath = PrepareStickyPath(piecePath);
closestDistance = ClosestDistance(stickyPath, pieceStickyPath);
}
}
}
if (closestDistance.isNull())
if (!StickyPieces(match))
{
return false;
}
const qreal extraZone = qBound(minStickyDistance, pieceGap * 50 / 100, maxStickyDistance);
const qreal length = closestDistance.length();
if (length > pieceGap && length <= pieceGap + extraZone)
if (match.m_closestDistance.isNull())
{
closestDistance.setLength(length - pieceGap);
QPointF diff = closestDistance.p2() - closestDistance.p1();
return false;
}
const qreal extraZone = qBound(minStickyDistance, match.m_pieceGap * 50 / 100, maxStickyDistance);
const qreal length = match.m_closestDistance.length();
if (length > match.m_pieceGap && length <= match.m_pieceGap + extraZone)
{
match.m_closestDistance.setLength(length - match.m_pieceGap);
QPointF const diff = match.m_closestDistance.p2() - match.m_closestDistance.p1();
dx = diff.x();
dy = diff.y();
return true;
}
if (length < pieceGap && length >= pieceGap - extraZone)
if (length < match.m_pieceGap && length >= match.m_pieceGap - extraZone)
{
closestDistance.setAngle(closestDistance.angle() + 180);
closestDistance.setLength(pieceGap - length);
QPointF diff = closestDistance.p2() - closestDistance.p1();
match.m_closestDistance.setAngle(match.m_closestDistance.angle() + 180);
match.m_closestDistance.setLength(match.m_pieceGap - length);
QPointF const diff = match.m_closestDistance.p2() - match.m_closestDistance.p1();
dx = diff.x();
dy = diff.y();
return true;
@ -471,6 +450,179 @@ void VPPiece::SetCopyNumber(quint16 newCopyNumber)
m_copyNumber = qMax(static_cast<quint16>(1), newCopyNumber);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::StickySheet(VStickyDistance &match) const -> bool
{
VPLayoutPtr const layout = Layout();
if (layout.isNull())
{
return false;
}
const qreal pieceGap = layout->LayoutSettings().GetPiecesGap();
if (pieceGap <= 0)
{
return false;
}
VPSheetPtr const sheet = Sheet();
if (sheet.isNull())
{
return false;
}
QRectF sheetRect = sheet->GetMarginsRect();
QVector<QPointF> path;
CastTo(GetMappedExternalContourPoints(), path);
QRectF const boundingRect = VLayoutPiece::BoundingRect(path);
if (!sheetRect.contains(boundingRect))
{
return true;
}
const qreal stickyDistance = maxStickyDistance;
QRectF const stickyZone =
QRectF(boundingRect.topLeft().x() - stickyDistance, boundingRect.topLeft().y() - stickyDistance,
boundingRect.width() + stickyDistance * 2, boundingRect.height() + stickyDistance * 2);
if (!stickyZone.intersects(sheetRect))
{
return true;
}
QVector<QPointF> const stickyPath = PrepareStickyPath(path);
if (!layout->LayoutSettings().IsCutOnFold())
{
sheetRect.adjust(accuracyPointOnLine, accuracyPointOnLine, -accuracyPointOnLine, -accuracyPointOnLine);
QVector<QPointF> const sheetPath{sheetRect.topLeft(), sheetRect.topRight(), sheetRect.bottomRight(),
sheetRect.bottomLeft(), sheetRect.topLeft()};
QVector<QPointF> const sheetStickyPath = PrepareStickyPath(sheetPath);
QLineF const distance = ClosestDistance(stickyPath, sheetStickyPath);
if (match.m_closestDistance.isNull() || distance.length() < match.m_closestDistance.length())
{
match.m_closestDistance = distance;
}
return true;
}
if (GetSeamAllowanceMirrorLine().isNull() || (!GetSeamAllowanceMirrorLine().isNull() && IsShowFullPiece()))
{ // regular piece
QVector<QPointF> sheetPath;
if (sheetRect.width() >= sheetRect.height())
{
sheetRect.adjust(accuracyPointOnLine, accuracyPointOnLine, -accuracyPointOnLine, -accuracyPointOnLine);
QPointF const shift(0, pieceGap / 2. - accuracyPointOnLine);
sheetPath = {sheetRect.topLeft() + shift, sheetRect.topRight() + shift, sheetRect.bottomRight(),
sheetRect.bottomLeft(), sheetRect.topLeft() + shift};
}
else
{
sheetRect.adjust(accuracyPointOnLine, accuracyPointOnLine, -accuracyPointOnLine, -accuracyPointOnLine);
QPointF const shift(pieceGap / 2. - accuracyPointOnLine, 0);
sheetPath = {sheetRect.topLeft(), sheetRect.topRight() - shift, sheetRect.bottomRight() - shift,
sheetRect.bottomLeft(), sheetRect.topLeft()};
}
QVector<QPointF> const sheetStickyPath = PrepareStickyPath(sheetPath);
QLineF const distance = ClosestDistance(stickyPath, sheetStickyPath);
if (match.m_closestDistance.isNull() || distance.length() < match.m_closestDistance.length())
{
match.m_closestDistance = distance;
}
return true;
}
// mirrored piece
QVector<QPointF> sheetPath;
if (sheetRect.width() >= sheetRect.height())
{
QPointF const shift(0, accuracyPointOnLine);
sheetPath = {sheetRect.topLeft() + shift, sheetRect.topRight() + shift};
}
else
{
QPointF const shift(accuracyPointOnLine, 0);
sheetPath = {sheetRect.topRight() - shift, sheetRect.bottomRight() - shift};
}
QVector<QPointF> const sheetStickyPath = PrepareStickyPath(sheetPath);
QLineF const distance = ClosestDistance(stickyPath, sheetStickyPath);
if (match.m_closestDistance.isNull() || distance.length() < match.m_closestDistance.length())
{
match.m_closestDistance = distance;
}
return true;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::StickyPieces(VStickyDistance &match) const -> bool
{
VPLayoutPtr const layout = Layout();
if (layout.isNull())
{
return false;
}
const qreal pieceGap = layout->LayoutSettings().GetPiecesGap();
if (pieceGap <= 0)
{
return false;
}
VPSheetPtr const sheet = Sheet();
if (sheet.isNull())
{
return false;
}
QList<VPPiecePtr> const allPieces = sheet->GetPieces();
if (allPieces.count() < 2)
{
return true;
}
QVector<QPointF> path;
CastTo(GetMappedExternalContourPoints(), path);
QRectF const boundingRect = VLayoutPiece::BoundingRect(path);
const qreal stickyDistance = pieceGap + minStickyDistance;
QRectF const stickyZone =
QRectF(boundingRect.topLeft().x() - stickyDistance, boundingRect.topLeft().y() - stickyDistance,
boundingRect.width() + stickyDistance * 2, boundingRect.height() + stickyDistance * 2);
QVector<QPointF> const stickyPath = PrepareStickyPath(path);
for (const auto &piece : allPieces)
{
if (piece.isNull() || piece->GetUniqueID() == GetUniqueID())
{
continue;
}
QVector<QPointF> piecePath;
CastTo(piece->GetMappedExternalContourPoints(), piecePath);
QRectF const pieceBoundingRect = VLayoutPiece::BoundingRect(piecePath);
if (stickyZone.intersects(pieceBoundingRect) || pieceBoundingRect.contains(stickyZone) ||
stickyZone.contains(pieceBoundingRect))
{
if (not VPPiece::PathsSuperposition(path, piecePath))
{
QVector<QPointF> const pieceStickyPath = PrepareStickyPath(piecePath);
QLineF const distance = ClosestDistance(stickyPath, pieceStickyPath);
if (match.m_closestDistance.isNull() || distance.length() < match.m_closestDistance.length())
{
match.m_closestDistance = distance;
match.m_pieceGap = pieceGap;
}
}
}
}
return true;
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::CleanPosition(const VPPiecePtr &piece)
{
@ -530,4 +682,6 @@ void VPPiece::CleanPosition(const VPPiecePtr &piece)
piece->SetPieceLabelRect(MapVector(piece->GetPieceLabelRect(), matrix));
piece->SetPatternLabelRect(MapVector(piece->GetPatternLabelRect(), matrix));
piece->SetSeamMirrorLine(matrix.map(piece->GetSeamMirrorLine()));
piece->SetSeamAllowanceMirrorLine(matrix.map(piece->GetSeamAllowanceMirrorLine()));
}

View File

@ -44,6 +44,12 @@
class VPLayout;
class VPSheet;
struct VStickyDistance
{
QLineF m_closestDistance{};
qreal m_pieceGap{0};
};
class VPPiece : public VLayoutPiece
{
Q_DECLARE_TR_FUNCTIONS(VPPiece) // NOLINT
@ -136,6 +142,9 @@ private:
quint16 m_copyNumber{1};
qreal m_zValue{1.0};
auto StickySheet(VStickyDistance &match) const -> bool;
auto StickyPieces(VStickyDistance &match) const -> bool;
};
//---------------------------------------------------------------------------------------------------------------------

View File

@ -143,7 +143,7 @@ void VPSheetSceneData::PrepareForExport()
m_rotationControls->setVisible(false);
m_rotationOrigin->setVisible(false);
VPLayoutPtr layout = m_layout.toStrongRef();
VPLayoutPtr const layout = m_layout.toStrongRef();
if (not layout.isNull())
{
m_showGridTmp = layout->LayoutSettings().GetShowGrid();
@ -152,7 +152,7 @@ void VPSheetSceneData::PrepareForExport()
m_showTilesTmp = layout->LayoutSettings().GetShowTiles();
layout->LayoutSettings().SetShowTiles(false);
VPSheetPtr sheet = layout->GetSheet(m_sheetUuid);
VPSheetPtr const sheet = layout->GetSheet(m_sheetUuid);
m_slectedPiecesTmp = sheet->GetSelectedPieces();
for (const auto &piece : qAsConst(m_slectedPiecesTmp))
@ -185,7 +185,7 @@ void VPSheetSceneData::CleanAfterExport()
m_rotationControls->setVisible(true);
VPLayoutPtr layout = m_layout.toStrongRef();
VPLayoutPtr const layout = m_layout.toStrongRef();
if (not layout.isNull())
{
layout->LayoutSettings().SetShowGrid(m_showGridTmp);
@ -544,7 +544,7 @@ void VPSheet::ValidateSuperpositionOfPieces() const
QVector<QPointF> path2;
CastTo(p->GetMappedExternalContourPoints(), path2);
bool superposition = VPPiece::PathsSuperposition(path1, path2);
bool const superposition = VPPiece::PathsSuperposition(path1, path2);
if (superposition)
{
hasSuperposition = superposition;
@ -556,7 +556,7 @@ void VPSheet::ValidateSuperpositionOfPieces() const
if (oldSuperpositionOfPieces != piece->HasSuperpositionWithPieces())
{
VPLayoutPtr layout = GetLayout();
VPLayoutPtr const layout = GetLayout();
if (not layout.isNull())
{
emit layout->PiecePositionValidityChanged(piece);
@ -574,15 +574,26 @@ void VPSheet::ValidatePieceOutOfBound(const VPPiecePtr &piece) const
}
const bool oldOutOfBound = piece->OutOfBound();
QRectF const sheetRect = GetMarginsRect();
QRectF pieceRect = piece->MappedDetailBoundingRect();
QRectF sheetRect = GetMarginsRect();
VPLayoutPtr const layout = GetLayout();
if (not layout.isNull() && layout->LayoutSettings().IsCutOnFold() && not piece->IsShowFullPiece() &&
!piece->GetSeamMirrorLine().isNull())
{
QLineF const foldLine = sheetRect.width() >= sheetRect.height()
? QLineF(sheetRect.topLeft(), sheetRect.topRight())
: QLineF(sheetRect.topRight(), sheetRect.bottomRight());
piece->SetOutOfBound(not VGObject::IsLineSegmentOnLineSegment(
foldLine, piece->GetMappedSeamAllowanceMirrorLine(), MmToPixel(0.5)));
}
else
{
QRectF const pieceRect = piece->MappedDetailBoundingRect();
piece->SetOutOfBound(not sheetRect.contains(pieceRect));
}
if (oldOutOfBound != piece->OutOfBound())
{
VPLayoutPtr layout = GetLayout();
if (not layout.isNull())
{
emit layout->PiecePositionValidityChanged(piece);
@ -593,7 +604,7 @@ void VPSheet::ValidatePieceOutOfBound(const VPPiecePtr &piece) const
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::ValidatePiecesOutOfBound() const
{
QList<VPPiecePtr> pieces = GetPieces();
QList<VPPiecePtr> const pieces = GetPieces();
for (const auto &piece : pieces)
{
ValidatePieceOutOfBound(piece);

View File

@ -28,6 +28,8 @@
#ifndef SCENEDEF_H
#define SCENEDEF_H
#include "qtypes.h"
enum class PGraphicsItem : int
{
Piece = 1,
@ -35,4 +37,7 @@ enum class PGraphicsItem : int
TransformationOrigin = 3
};
constexpr qreal foldTextMargin = 5;
constexpr int foldFontSize = 34;
#endif // SCENEDEF_H

View File

@ -45,6 +45,7 @@
#include "../vformat/vsinglelineoutlinechar.h"
#include "../vgeometry/vlayoutplacelabel.h"
#include "../vlayout/vboundary.h"
#include "../vlayout/vfoldline.h"
#include "../vlayout/vgraphicsfillitem.h"
#include "../vlayout/vlayoutpiecepath.h"
#include "../vlayout/vtextmanager.h"
@ -53,7 +54,9 @@
#include "../vmisc/svgfont/vsvgfontengine.h"
#include "../vmisc/theme/vscenestylesheet.h"
#include "../vpapplication.h"
#include "../vpatterndb/vpiecepath.h"
#include "compatibility.h"
#include "qtpreprocessorsupport.h"
#include "undocommands/vpundomovepieceonsheet.h"
#include "undocommands/vpundopiecemove.h"
#include "vpiecegrainline.h"
@ -72,7 +75,7 @@ namespace
{
//---------------------------------------------------------------------------------------------------------------------
inline auto LineMatrix(const VPPiecePtr &piece, const QPointF &topLeft, qreal angle, const QPointF &linePos,
int maxLineWidth, qreal maxLabelHeight) -> QTransform
int maxLineWidth) -> QTransform
{
if (piece.isNull())
{
@ -82,26 +85,27 @@ inline auto LineMatrix(const VPPiecePtr &piece, const QPointF &topLeft, qreal an
QTransform labelMatrix;
labelMatrix.translate(topLeft.x(), topLeft.y());
if (piece->IsVerticallyFlipped() || piece->IsHorizontallyFlipped())
if ((piece->IsVerticallyFlipped() && piece->IsHorizontallyFlipped()) ||
(!piece->IsVerticallyFlipped() && !piece->IsHorizontallyFlipped()))
{
if (piece->IsVerticallyFlipped())
labelMatrix.rotate(angle);
}
else if (piece->IsVerticallyFlipped() || piece->IsHorizontallyFlipped())
{
if (piece->IsVerticallyFlipped() && !piece->IsHorizontallyFlipped())
{
labelMatrix.scale(-1, 1);
labelMatrix.rotate(-angle);
labelMatrix.translate(-maxLineWidth, 0);
}
if (piece->IsHorizontallyFlipped())
if (piece->IsHorizontallyFlipped() && !piece->IsVerticallyFlipped())
{
labelMatrix.scale(1, -1);
labelMatrix.scale(-1, 1);
labelMatrix.rotate(-angle);
labelMatrix.translate(0, -maxLabelHeight);
labelMatrix.translate(-maxLineWidth, 0);
}
}
else
{
labelMatrix.rotate(angle);
}
labelMatrix.translate(linePos.x(), linePos.y()); // Each string has own position
labelMatrix *= piece->GetMatrix();
@ -177,73 +181,7 @@ inline auto LineAlign(const TextLine &tl, const QString &text, const VSvgFontEng
//---------------------------------------------------------------------------------------------------------------------
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;
return {VSceneStylesheet::ManualLayoutStyle().PieceSelectionBrushColor()};
}
} // namespace
@ -283,6 +221,8 @@ auto VPGraphicsPiece::boundingRect() const -> QRectF
shape.addPath(m_passmarks);
shape.addPath(m_placeLabels);
shape.addPath(m_stickyPath);
shape.addPath(m_foldLineMarkPath);
shape.addPath(m_foldLineLabelPath);
VPSettings *settings = VPApplication::VApp()->PuzzleSettings();
const qreal halfPenWidth = settings->GetLayoutLineWidth() / 2.;
@ -308,7 +248,7 @@ void VPGraphicsPiece::paint(QPainter *painter, const QStyleOptionGraphicsItem *o
Q_UNUSED(option);
VPSettings *settings = VPApplication::VApp()->PuzzleSettings();
QPen pen(PieceColor(), settings->GetLayoutLineWidth(), Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
QPen const pen(PieceColor(), settings->GetLayoutLineWidth(), Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
painter->setPen(pen);
PaintPiece(painter);
@ -459,7 +399,7 @@ void VPGraphicsPiece::InitLabels()
m_labelPathItems.clear();
m_labelTextItems.clear();
VPPiecePtr piece = m_piece.toStrongRef();
VPPiecePtr const piece = m_piece.toStrongRef();
if (piece.isNull())
{
return;
@ -481,7 +421,7 @@ void VPGraphicsPiece::SetStickyPoints(const QVector<QPointF> &newStickyPoint)
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::InitPieceLabelSVGFont(const QVector<QPointF> &labelShape, const VTextManager &tm)
{
VPPiecePtr piece = m_piece.toStrongRef();
VPPiecePtr const piece = m_piece.toStrongRef();
if (piece.isNull())
{
return;
@ -496,16 +436,16 @@ void VPGraphicsPiece::InitPieceLabelSVGFont(const QVector<QPointF> &labelShape,
VSvgFontEngine engine =
db->FontEngine(tm.GetSVGFontFamily(), SVGFontStyle::Normal, SVGFontWeight::Normal, tm.GetSVGFontPointSize());
VSvgFont svgFont = engine.Font();
VSvgFont const svgFont = engine.Font();
if (!svgFont.IsValid())
{
QString errorMsg = QStringLiteral("Invalid SVG font '%1'. Fallback to outline font.").arg(svgFont.Name());
QString const errorMsg = QStringLiteral("Invalid SVG font '%1'. Fallback to outline font.").arg(svgFont.Name());
qDebug() << errorMsg;
InitPieceLabelOutlineFont(labelShape, tm);
return;
}
qreal penWidth = VPApplication::VApp()->PuzzleSettings()->GetLayoutLineWidth();
qreal const penWidth = VPApplication::VApp()->PuzzleSettings()->GetLayoutLineWidth();
const qreal dW = QLineF(labelShape.at(0), labelShape.at(1)).length();
const qreal dH = QLineF(labelShape.at(1), labelShape.at(2)).length();
@ -517,8 +457,6 @@ 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);
@ -532,8 +470,7 @@ 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, labelHeight);
const QTransform lineMatrix = LineMatrix(piece, labelShape.at(0), angle, QPointF(dX, dY), maxLineWidth);
auto *item = new QGraphicsPathItem(this);
item->setPath(engine.DrawPath(QPointF(), qsText));
@ -549,7 +486,7 @@ void VPGraphicsPiece::InitPieceLabelSVGFont(const QVector<QPointF> &labelShape,
item->setTransform(lineMatrix);
m_labelPathItems.append(item);
dY += engine.FontHeight() + penWidth + tm.GetSpacing();
dY += engine.FontHeight() - penWidth * 2 + tm.GetSpacing();
}
}
@ -587,31 +524,19 @@ 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());
VSingleLineOutlineChar corrector(fnt);
if (settings->GetSingleStrokeOutlineFont() && !corrector.IsPopulated())
{
corrector.LoadCorrections(settings->GetPathFontCorrections());
}
QFontMetrics fm(fnt);
QFontMetrics const fm(fnt);
if (dY + fm.height() > dH)
{
break;
}
const QString qsText = tl.m_qsText;
const qreal dX = LineAlign(tl, qsText, fm, dW);
const qreal dX = LineAlign(tl, tl.m_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, labelHeight);
const QTransform lineMatrix = LineMatrix(piece, labelShape.at(0), angle, QPointF(dX, dY), maxLineWidth);
if (textAsPaths)
{
@ -619,8 +544,14 @@ void VPGraphicsPiece::InitPieceLabelOutlineFont(const QVector<QPointF> &labelSha
if (settings->GetSingleStrokeOutlineFont())
{
VSingleLineOutlineChar const corrector(fnt);
if (!corrector.IsPopulated())
{
corrector.LoadCorrections(settings->GetPathFontCorrections());
}
int w = 0;
for (auto c : qAsConst(qsText))
for (auto c : qAsConst(tl.m_qsText))
{
path.addPath(corrector.DrawChar(w, static_cast<qreal>(fm.ascent()), c));
w += TextWidth(fm, c);
@ -628,7 +559,7 @@ void VPGraphicsPiece::InitPieceLabelOutlineFont(const QVector<QPointF> &labelSha
}
else
{
path.addText(0, static_cast<qreal>(fm.ascent()), fnt, qsText);
path.addText(0, static_cast<qreal>(fm.ascent()), fnt, tl.m_qsText);
}
auto *item = new QGraphicsPathItem(this);
@ -644,18 +575,18 @@ void VPGraphicsPiece::InitPieceLabelOutlineFont(const QVector<QPointF> &labelSha
item->setTransform(lineMatrix);
m_labelPathItems.append(item);
dY += fm.height() + penWidth + tm.GetSpacing();
dY += fm.height() + penWidth + MmToPixel(1.5) + tm.GetSpacing();
}
else
{
auto *item = new QGraphicsSimpleTextItem(this);
item->setFont(fnt);
item->setText(qsText);
item->setText(tl.m_qsText);
item->setBrush(QBrush(color));
item->setTransform(lineMatrix);
m_labelTextItems.append(item);
dY += (fm.height() + tm.GetSpacing());
dY += (fm.height() + MmToPixel(1.5) + tm.GetSpacing());
}
}
}
@ -706,8 +637,10 @@ void VPGraphicsPiece::PaintPiece(QPainter *painter)
m_passmarks = QPainterPath();
m_placeLabels = QPainterPath();
m_stickyPath = QPainterPath();
m_foldLineMarkPath = QPainterPath();
m_foldLineLabelPath = QPainterPath();
VPPiecePtr piece = m_piece.toStrongRef();
VPPiecePtr const piece = m_piece.toStrongRef();
if (piece.isNull())
{
return;
@ -728,22 +661,29 @@ void VPGraphicsPiece::PaintPiece(QPainter *painter)
// initialises the place labels (buttons etc)
PaintPlaceLabels(painter, piece);
PaintMirrorLine(painter, piece);
PaintFoldLine(painter, piece);
PaintStickyPath(painter);
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::PaintSeamLine(QPainter *painter, const VPPiecePtr &piece)
{
if (piece->IsSeamAllowance() && not piece->IsHideMainPath() && not piece->IsSeamAllowanceBuiltIn())
if (piece->IsHideMainPath() && piece->IsSeamAllowance() && not piece->IsSeamAllowanceBuiltIn())
{
QVector<VLayoutPoint> seamLinePoints = piece->GetMappedContourPoints();
return;
}
QVector<VLayoutPoint> const seamLinePoints = piece->GetMappedFullContourPoints();
if (seamLinePoints.isEmpty())
{
return;
}
VPLayoutPtr layout = piece->Layout();
VPLayoutPtr const layout = piece->Layout();
if (layout.isNull())
{
return;
@ -751,13 +691,17 @@ void VPGraphicsPiece::PaintSeamLine(QPainter *painter, const VPPiecePtr &piece)
if (layout->LayoutSettings().IsBoundaryTogetherWithNotches())
{
QVector<VLayoutPassmark> passmarks = piece->GetMappedPassmarks();
QVector<VLayoutPassmark> const passmarks = piece->GetMappedPassmarks();
bool seamAllowance = piece->IsSeamAllowance() && piece->IsSeamAllowanceBuiltIn();
bool builtInSeamAllowance = piece->IsSeamAllowance() && piece->IsSeamAllowanceBuiltIn();
bool const seamAllowance = piece->IsSeamAllowance() && piece->IsSeamAllowanceBuiltIn();
bool const builtInSeamAllowance = piece->IsSeamAllowance() && piece->IsSeamAllowanceBuiltIn();
VBoundary boundary(seamLinePoints, seamAllowance, builtInSeamAllowance);
boundary.SetPieceName(piece->GetName());
if (piece->IsShowFullPiece())
{
boundary.SetMirrorLine(piece->GetMappedSeamMirrorLine());
}
const QList<VBoundarySequenceItemData> sequence = boundary.Combine(passmarks, false, false);
QVector<QPointF> combinedBoundary;
@ -789,14 +733,13 @@ void VPGraphicsPiece::PaintSeamLine(QPainter *painter, const VPPiecePtr &piece)
painter->restore();
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::PaintCuttingLine(QPainter *painter, const VPPiecePtr &piece)
{
if (piece->IsSeamAllowance() && not piece->IsSeamAllowanceBuiltIn())
{
QVector<VLayoutPoint> cuttingLinepoints = piece->GetMappedSeamAllowancePoints();
QVector<VLayoutPoint> cuttingLinepoints = piece->GetMappedFullSeamAllowancePoints();
if (cuttingLinepoints.isEmpty())
{
return;
@ -817,6 +760,10 @@ void VPGraphicsPiece::PaintCuttingLine(QPainter *painter, const VPPiecePtr &piec
VBoundary boundary(cuttingLinepoints, seamAllowance, builtInSeamAllowance);
boundary.SetPieceName(piece->GetName());
if (piece->IsShowFullPiece())
{
boundary.SetMirrorLine(piece->GetMappedSeamAllowanceMirrorLine());
}
const QList<VBoundarySequenceItemData> sequence = boundary.Combine(passmarks, false, false);
QVector<QPointF> combinedBoundary;
@ -853,11 +800,22 @@ void VPGraphicsPiece::PaintCuttingLine(QPainter *painter, const VPPiecePtr &piec
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::PaintInternalPaths(QPainter *painter, const VPPiecePtr &piece)
{
QVector<VLayoutPiecePath> internalPaths = piece->GetInternalPaths();
QVector<VLayoutPiecePath> const internalPaths = piece->GetInternalPaths();
for (const auto &piecePath : internalPaths)
{
QPainterPath path = piece->GetMatrix().map(piecePath.GetPainterPath());
if (!piecePath.IsNotMirrored() && piece->IsShowFullPiece() && !piece->GetSeamMirrorLine().isNull())
{
QVector<VLayoutPoint> points = piecePath.Points();
const QTransform matrix = VGObject::FlippingMatrix(piece->GetSeamMirrorLine());
std::transform(points.begin(), points.end(), points.begin(),
[matrix](const VLayoutPoint &point) { return VAbstractPiece::MapPoint(point, matrix); });
QVector<QPointF> casted;
CastTo(points, casted);
path.addPath(piece->GetMatrix().map(VPiecePath::MakePainterPath(casted)));
}
if (painter != nullptr)
{
painter->save();
@ -874,7 +832,7 @@ void VPGraphicsPiece::PaintInternalPaths(QPainter *painter, const VPPiecePtr &pi
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::PaintPassmarks(QPainter *painter, const VPPiecePtr &piece)
{
VPLayoutPtr layout = piece->Layout();
VPLayoutPtr const layout = piece->Layout();
if (layout.isNull())
{
return;
@ -885,37 +843,67 @@ void VPGraphicsPiece::PaintPassmarks(QPainter *painter, const VPPiecePtr &piece)
return;
}
QVector<VLayoutPassmark> passmarks = piece->GetMappedPassmarks();
for (auto &passmark : passmarks)
QVector<VLayoutPassmark> const passmarks = piece->GetMappedPassmarks();
for (const auto &passmark : passmarks)
{
QPainterPath passmarkPath;
for (auto &line : passmark.lines)
for (const auto &line : passmark.lines)
{
passmarkPath.moveTo(line.p1());
passmarkPath.lineTo(line.p2());
}
m_passmarks.addPath(passmarkPath);
QLineF const seamAllowanceMirrorLine = piece->GetMappedSeamAllowanceMirrorLine();
if (!seamAllowanceMirrorLine.isNull() && piece->IsShowFullPiece())
{
if (!VGObject::IsPointOnLineviaPDP(passmark.baseLine.p1(), seamAllowanceMirrorLine.p1(),
seamAllowanceMirrorLine.p2()))
{
QPainterPath mirroredPassmaksPath;
for (const auto &line : passmark.lines)
{
mirroredPassmaksPath.moveTo(line.p1());
mirroredPassmaksPath.lineTo(line.p2());
}
const QTransform matrix = VGObject::FlippingMatrix(seamAllowanceMirrorLine);
m_passmarks.addPath(matrix.map(mirroredPassmaksPath));
}
}
if (painter != nullptr)
{
painter->save();
painter->setBrush(NoBrush());
painter->drawPath(passmarkPath);
painter->drawPath(m_passmarks);
painter->restore();
}
m_passmarks.addPath(passmarkPath);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::PaintPlaceLabels(QPainter *painter, const VPPiecePtr &piece)
{
QVector<VLayoutPlaceLabel> placeLabels = piece->GetPlaceLabels();
for (auto &placeLabel : placeLabels)
QVector<VLayoutPlaceLabel> const placeLabels = piece->GetPlaceLabels();
for (const auto &placeLabel : placeLabels)
{
QPainterPath path =
VAbstractPiece::LabelShapePath(piece->MapPlaceLabelShape(VAbstractPiece::PlaceLabelShape(placeLabel)));
if (!placeLabel.IsNotMirrored() && piece->IsShowFullPiece() && !piece->GetSeamMirrorLine().isNull())
{
PlaceLabelImg shape = VAbstractPiece::PlaceLabelShape(placeLabel);
const QTransform matrix = VGObject::FlippingMatrix(piece->GetSeamMirrorLine());
for (auto &points : shape)
{
std::transform(points.begin(), points.end(), points.begin(),
[matrix](const VLayoutPoint &point) { return VAbstractPiece::MapPoint(point, matrix); });
}
path.addPath(VAbstractPiece::LabelShapePath(piece->MapPlaceLabelShape(shape)));
}
if (painter != nullptr)
{
painter->save();
@ -955,6 +943,127 @@ void VPGraphicsPiece::PaintStickyPath(QPainter *painter)
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::PaintMirrorLine(QPainter *painter, const VPPiecePtr &piece)
{
if (piece->IsShowFullPiece())
{
bool mirrorFlag = false;
QPainterPath mirrorLinePath;
if (not piece->IsSeamAllowance() || piece->IsSeamAllowanceBuiltIn())
{
QLineF const seamMirrorLine = piece->GetMappedSeamMirrorLine();
if (!seamMirrorLine.isNull())
{
QPainterPath mirrorPath;
mirrorPath.moveTo(seamMirrorLine.p1());
mirrorPath.lineTo(seamMirrorLine.p2());
mirrorLinePath.addPath(mirrorPath);
mirrorFlag = true;
}
}
else if (not piece->IsSeamAllowanceBuiltIn())
{
QLineF const seamAllowanceMirrorLine = piece->GetMappedSeamAllowanceMirrorLine();
if (!seamAllowanceMirrorLine.isNull())
{
QPainterPath mirrorPath;
mirrorPath.moveTo(seamAllowanceMirrorLine.p1());
mirrorPath.lineTo(seamAllowanceMirrorLine.p2());
mirrorLinePath.addPath(mirrorPath);
mirrorFlag = true;
}
}
if (mirrorFlag && painter != nullptr)
{
painter->save();
QPen pen = painter->pen();
pen.setStyle(Qt::DashDotLine);
painter->setPen(pen);
painter->drawPath(mirrorLinePath);
painter->restore();
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::PaintFoldLine(QPainter *painter, const VPPiecePtr &piece)
{
if (piece->GetFoldLineType() == FoldLineType::None)
{
return;
}
VFoldLine const fLine = piece->FoldLine();
QVector<QPainterPath> const shape = fLine.FoldLinePath();
if (shape.isEmpty())
{
return;
}
VCommonSettings *settings = VAbstractApplication::VApp()->Settings();
if (!m_textAsPaths && !settings->GetSingleStrokeOutlineFont() && !settings->GetSingleLineFonts())
{
if (m_foldLineLabelText == nullptr)
{
m_foldLineLabelText = new QGraphicsSimpleTextItem(this);
}
fLine.UpdateFoldLineLabel(m_foldLineLabelText);
}
else
{
if (m_foldLineLabelText != nullptr)
{
m_foldLineLabelText->setVisible(false);
}
}
const bool singleLineFont = settings->GetSingleStrokeOutlineFont() || settings->GetSingleLineFonts();
if (piece->GetFoldLineType() == FoldLineType::ThreeDots || piece->GetFoldLineType() == FoldLineType::ThreeX ||
piece->GetFoldLineType() == FoldLineType::TwoArrows)
{
m_foldLineMarkPath.addPath(shape.constFirst());
}
else if (piece->GetFoldLineType() == FoldLineType::Text)
{
if (singleLineFont || m_textAsPaths)
{
m_foldLineLabelPath.addPath(shape.constFirst());
}
}
else
{
m_foldLineMarkPath.addPath(shape.constFirst());
if (shape.size() > 1 && (singleLineFont || m_textAsPaths))
{
m_foldLineLabelPath.addPath(shape.constLast());
}
}
if (painter != nullptr)
{
painter->save();
painter->setBrush(Qt::SolidPattern);
painter->drawPath(m_foldLineMarkPath);
painter->restore();
qreal const penWidth = VPApplication::VApp()->PuzzleSettings()->GetLayoutLineWidth();
painter->save();
QPen pen = painter->pen();
pen.setWidthF(penWidth * qMin(piece->GetXScale(), piece->GetYScale()));
painter->setPen(pen);
painter->setBrush(singleLineFont ? Qt::NoBrush : Qt::SolidPattern);
painter->drawPath(m_foldLineLabelPath);
painter->restore();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::GroupMove(const QPointF &pos)
{

View File

@ -109,6 +109,9 @@ private:
QVector<QPointF> m_stickyPoints{};
QPainterPath m_stickyPath{};
QPainterPath m_foldLineMarkPath{};
QPainterPath m_foldLineLabelPath{};
bool m_hasStickyPosition{false};
qreal m_stickyTranslateX{0};
qreal m_stickyTranslateY{0};
@ -120,6 +123,7 @@ private:
VGraphicsFillItem *m_grainlineItem{nullptr};
QVector<QGraphicsPathItem *> m_labelPathItems{};
QVector<QGraphicsSimpleTextItem *> m_labelTextItems{};
QGraphicsSimpleTextItem *m_foldLineLabelText{nullptr};
void InitLabels();
void InitPieceLabelSVGFont(const QVector<QPointF> &labelShape, const VTextManager &tm);
@ -133,6 +137,8 @@ private:
void PaintPassmarks(QPainter *painter, const VPPiecePtr &piece);
void PaintPlaceLabels(QPainter *painter, const VPPiecePtr &piece);
void PaintStickyPath(QPainter *painter);
void PaintMirrorLine(QPainter *painter, const VPPiecePtr &piece);
void PaintFoldLine(QPainter *painter, const VPPiecePtr &piece);
void GroupMove(const QPointF &pos);

View File

@ -29,11 +29,65 @@
#include "vpgraphicssheet.h"
#include "../layout/vplayout.h"
#include "../layout/vpsheet.h"
#include "qnamespace.h"
#include "theme/vscenestylesheet.h"
#include "../vlayout/vlayoutpiece.h"
#include "../vmisc/theme/vscenestylesheet.h"
#include "../vptilefactory.h"
#include "../vwidgets/vpiecegrainline.h"
#include "scenedef.h"
#include <QApplication>
#include <QFontMetrics>
#include <QtMath>
namespace
{
constexpr qreal foldArrowMargin = 20;
//---------------------------------------------------------------------------------------------------------------------
auto SwapRect(const QRectF &rect) -> QRectF
{
return {rect.center().x() - rect.height() / 2.0, rect.center().y() - rect.width() / 2.0, rect.height(),
rect.width()};
}
//---------------------------------------------------------------------------------------------------------------------
void PaintVerticalFoldShadow(QPainter *painter, const QRectF &sheetRect)
{
QLineF shadowLine(sheetRect.topLeft(), sheetRect.bottomLeft());
shadowLine.setLength(shadowLine.length() * 0.97);
shadowLine.setAngle(shadowLine.angle() - 1.5);
QPointF const shadowP =
VGObject::ClosestPoint(QLineF(sheetRect.topLeft(), sheetRect.bottomLeft()), shadowLine.p2());
painter->drawLine(shadowLine);
painter->drawLine(QLineF(shadowLine.p2(), shadowP));
QPolygonF const shadow{sheetRect.topLeft(), shadowLine.p2(), shadowP, sheetRect.topLeft()};
painter->setBrush(QBrush(VSceneStylesheet::ManualLayoutStyle().SheetFoldShadowColor()));
painter->drawPolygon(shadow);
}
//---------------------------------------------------------------------------------------------------------------------
void PaintHorizontalFoldShadow(QPainter *painter, const QRectF &sheetRect)
{
QLineF shadowLine(sheetRect.topRight(), sheetRect.topLeft());
shadowLine.setLength(shadowLine.length() * 0.97);
shadowLine.setAngle(shadowLine.angle() - 1.5);
QPointF const shadowP = VGObject::ClosestPoint(QLineF(sheetRect.topRight(), sheetRect.topLeft()), shadowLine.p2());
painter->drawLine(shadowLine);
painter->drawLine(QLineF(shadowLine.p2(), shadowP));
QPolygonF const shadow{sheetRect.topRight(), shadowLine.p2(), shadowP, sheetRect.topRight()};
painter->setBrush(QBrush(VSceneStylesheet::ManualLayoutStyle().SheetFoldShadowColor()));
painter->drawPolygon(shadow);
}
} // namespace
//---------------------------------------------------------------------------------------------------------------------
VPGraphicsSheet::VPGraphicsSheet(const VPLayoutPtr &layout, QGraphicsItem *parent)
: QGraphicsItem(parent),
@ -47,92 +101,22 @@ void VPGraphicsSheet::paint(QPainter *painter, const QStyleOptionGraphicsItem *o
Q_UNUSED(widget);
Q_UNUSED(option);
bool ignoreMargins = true;
VPLayoutPtr layout = m_layout.toStrongRef();
if (!layout.isNull())
{
VPSheetPtr sheet = layout->GetFocusedSheet();
if (!sheet.isNull())
{
ignoreMargins = sheet->IgnoreMargins();
}
}
if (m_showMargin && !ignoreMargins)
{
QPen pen(VSceneStylesheet::ManualLayoutStyle().SheetMarginColor(), 1.5, Qt::SolidLine, Qt::RoundCap,
Qt::RoundJoin);
pen.setCosmetic(true);
painter->save();
painter->setPen(pen);
painter->drawRect(GetMarginsRect());
painter->restore();
}
QRectF sheetRect = GetSheetRect();
if (m_showBorder)
{
QPen pen(VSceneStylesheet::ManualLayoutStyle().SheetBorderColor(), 1.5, Qt::SolidLine, Qt::RoundCap,
Qt::RoundJoin);
pen.setCosmetic(true);
painter->save();
painter->setPen(pen);
painter->drawRect(sheetRect);
painter->restore();
}
if (not layout.isNull() && layout->LayoutSettings().GetShowGrid())
{
QPen pen(VSceneStylesheet::ManualLayoutStyle().SheetGridColor(), 1.5, Qt::SolidLine, Qt::RoundCap,
Qt::RoundJoin);
pen.setCosmetic(true);
painter->save();
painter->setPen(pen);
qreal colWidth = layout->LayoutSettings().GetGridColWidth();
if (colWidth > 0)
{
qreal colX = colWidth;
while (colX < sheetRect.right())
{
QLineF line = QLineF(colX, 0, colX, sheetRect.bottom());
painter->drawLine(line);
colX += colWidth;
}
}
qreal rowHeight = layout->LayoutSettings().GetGridRowHeight();
if (rowHeight > 0)
{
qreal rowY = rowHeight;
while (rowY < sheetRect.bottom())
{
QLineF line = QLineF(0, rowY, sheetRect.right(), rowY);
painter->drawLine(line);
rowY += rowHeight;
}
}
painter->restore();
}
PaintMargins(painter);
PaintBorder(painter);
PaintFold(painter);
PaintGrid(painter);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsSheet::GetSheetRect() const -> QRectF
{
VPLayoutPtr layout = m_layout.toStrongRef();
VPLayoutPtr const layout = m_layout.toStrongRef();
if (layout.isNull())
{
return {};
}
VPSheetPtr sheet = layout->GetFocusedSheet();
VPSheetPtr const sheet = layout->GetFocusedSheet();
if (sheet.isNull())
{
return {};
@ -143,13 +127,13 @@ auto VPGraphicsSheet::GetSheetRect() const -> QRectF
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsSheet::GetMarginsRect() const -> QRectF
{
VPLayoutPtr layout = m_layout.toStrongRef();
VPLayoutPtr const layout = m_layout.toStrongRef();
if (layout.isNull())
{
return {};
}
VPSheetPtr sheet = layout->GetFocusedSheet();
VPSheetPtr const sheet = layout->GetFocusedSheet();
if (sheet.isNull())
{
return {};
@ -175,8 +159,321 @@ void VPGraphicsSheet::RefreshBoundingRect()
prepareGeometryChange();
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsSheet::PaintVerticalFold(QPainter *painter, const QRectF &sheetRect) const
{
VPLayoutPtr const layout = m_layout.toStrongRef();
if (not layout.isNull() && layout->LayoutSettings().IsCutOnFold())
{
QString const foldText = FoldText();
painter->save();
QFont font = QApplication::font();
font.setPointSize(foldFontSize);
painter->setFont(font);
QRectF textRect = painter->fontMetrics().boundingRect(foldText);
int const textDescent = painter->fontMetrics().descent();
QPointF const textPosition(sheetRect.center().x() - textRect.width() / 2.,
sheetRect.topLeft().y() - foldTextMargin - textDescent);
painter->drawText(textPosition, foldText);
textRect.translate(sheetRect.center() - textRect.center());
textRect.translate(0, -(sheetRect.center().y() - sheetRect.topLeft().y()) - foldTextMargin -
textRect.height() / 2.);
// painter->drawRect(textRect); // uncomment for debug
painter->restore();
if (sheetRect.width() >= textRect.width() * 2)
{
qreal const baseY = textRect.center().y();
qreal const arrowMargin = foldArrowMargin + textRect.width() / 2.;
QLineF const leftLine(QPointF(sheetRect.topLeft().x(), baseY),
QPointF(sheetRect.center().x() - arrowMargin, baseY));
VPieceGrainline const leftArrow(leftLine, GrainlineArrowDirection::oneWayDown);
QPainterPath leftArrowPath = VLayoutPiece::GrainlinePath(leftArrow.Shape());
leftArrowPath.setFillRule(Qt::WindingFill);
painter->save();
QPen pen = painter->pen();
pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::RoundJoin);
painter->setPen(pen);
painter->setBrush(QBrush(pen.color(), Qt::SolidPattern));
painter->drawPath(leftArrowPath);
painter->restore();
QLineF const rightLine(QPointF(sheetRect.center().x() + arrowMargin, baseY),
QPointF(sheetRect.topRight().x(), baseY));
VPieceGrainline const rightArrow(rightLine, GrainlineArrowDirection::oneWayUp);
QPainterPath rightArrowPath = VLayoutPiece::GrainlinePath(rightArrow.Shape());
rightArrowPath.setFillRule(Qt::WindingFill);
painter->save();
pen = painter->pen();
pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::RoundJoin);
painter->setPen(pen);
painter->setBrush(QBrush(pen.color(), Qt::SolidPattern));
painter->drawPath(rightArrowPath);
painter->restore();
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsSheet::PaintHorizontalFold(QPainter *painter, const QRectF &sheetRect) const
{
VPLayoutPtr const layout = m_layout.toStrongRef();
if (not layout.isNull() && layout->LayoutSettings().IsCutOnFold())
{
QString const foldText = FoldText();
painter->save();
QFont font = QApplication::font();
font.setPointSize(foldFontSize);
painter->setFont(font);
QRectF const textRect = painter->fontMetrics().boundingRect(foldText);
// int const textAscent = painter->fontMetrics().ascent();
int const textDescent = painter->fontMetrics().descent();
QPointF const textPosition(sheetRect.center().x() - textRect.width() / 2.,
sheetRect.center().y() - sheetRect.width() / 2. - foldTextMargin - textDescent);
painter->translate(sheetRect.center());
painter->rotate(90);
painter->translate(-sheetRect.center());
painter->drawText(textPosition, foldText);
painter->restore();
QRectF swappedRect = SwapRect(textRect);
swappedRect.translate(sheetRect.center() - swappedRect.center());
swappedRect.translate(
(sheetRect.topRight().x() - sheetRect.center().x()) + foldTextMargin + textRect.height() / 2., 0);
// painter->drawRect(swappedRect); // uncomment for debug
if (sheetRect.height() >= textRect.width() * 2)
{
// qreal const baseX = sheetRect.topRight().x() + foldTextMargin + textDescent + textAscent / 2.;
qreal const baseX = swappedRect.center().x();
qreal const arrowMargin = foldArrowMargin + textRect.width() / 2.;
QLineF const leftLine(QPointF(baseX, sheetRect.topRight().y()),
QPointF(baseX, sheetRect.center().y() - arrowMargin));
VPieceGrainline const leftArrow(leftLine, GrainlineArrowDirection::oneWayDown);
QPainterPath leftArrowPath = VLayoutPiece::GrainlinePath(leftArrow.Shape());
leftArrowPath.setFillRule(Qt::WindingFill);
painter->save();
QPen pen = painter->pen();
pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::RoundJoin);
painter->setPen(pen);
painter->setBrush(QBrush(pen.color(), Qt::SolidPattern));
painter->drawPath(leftArrowPath);
painter->restore();
QLineF const rightLine(QPointF(baseX, sheetRect.center().y() + arrowMargin),
QPointF(baseX, sheetRect.bottomRight().y()));
VPieceGrainline const rightArrow(rightLine, GrainlineArrowDirection::oneWayUp);
QPainterPath rightArrowPath = VLayoutPiece::GrainlinePath(rightArrow.Shape());
rightArrowPath.setFillRule(Qt::WindingFill);
painter->save();
pen = painter->pen();
pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::RoundJoin);
painter->setPen(pen);
painter->setBrush(QBrush(pen.color(), Qt::SolidPattern));
painter->drawPath(rightArrowPath);
painter->restore();
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsSheet::PaintMargins(QPainter *painter) const
{
VPLayoutPtr const layout = m_layout.toStrongRef();
if (layout.isNull())
{
return;
}
bool ignoreMargins = true;
VPSheetPtr const sheet = layout->GetFocusedSheet();
if (!sheet.isNull())
{
ignoreMargins = sheet->IgnoreMargins();
}
if (m_showMargin && !ignoreMargins)
{
QPen pen(VSceneStylesheet::ManualLayoutStyle().SheetMarginColor(), 1.5, Qt::SolidLine, Qt::RoundCap,
Qt::RoundJoin);
pen.setCosmetic(true);
painter->save();
painter->setPen(pen);
painter->drawRect(GetMarginsRect());
painter->restore();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsSheet::PaintBorder(QPainter *painter) const
{
QRectF const sheetRect = GetSheetRect();
if (m_showBorder)
{
QPen pen(VSceneStylesheet::ManualLayoutStyle().SheetBorderColor(), 1.5, Qt::SolidLine, Qt::RoundCap,
Qt::RoundJoin);
pen.setCosmetic(true);
painter->save();
painter->setPen(pen);
painter->drawRect(sheetRect);
VPLayoutPtr const layout = m_layout.toStrongRef();
if (!layout.isNull() && layout->LayoutSettings().IsCutOnFold())
{
if (sheetRect.width() >= sheetRect.height())
{
PaintVerticalFoldShadow(painter, sheetRect);
}
else
{
PaintHorizontalFoldShadow(painter, sheetRect);
}
}
painter->restore();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsSheet::PaintFold(QPainter *painter) const
{
VPLayoutPtr const layout = m_layout.toStrongRef();
if (!layout.isNull() && layout->LayoutSettings().IsCutOnFold())
{
QRectF const sheetRect = GetSheetRect();
QRectF const foldField = m_showBorder ? sheetRect : FoldField(GetMarginsRect());
if (sheetRect.width() >= sheetRect.height())
{
PaintVerticalFold(painter, foldField);
}
else
{
PaintHorizontalFold(painter, foldField);
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsSheet::PaintGrid(QPainter *painter) const
{
VPLayoutPtr const layout = m_layout.toStrongRef();
if (not layout.isNull() && layout->LayoutSettings().GetShowGrid())
{
QPen pen(VSceneStylesheet::ManualLayoutStyle().SheetGridColor(), 1.5, Qt::SolidLine, Qt::RoundCap,
Qt::RoundJoin);
pen.setCosmetic(true);
painter->save();
painter->setPen(pen);
QRectF const sheetRect = GetSheetRect();
qreal const colWidth = layout->LayoutSettings().GetGridColWidth();
if (colWidth > 0)
{
qreal colX = colWidth;
while (colX < sheetRect.right())
{
QLineF const line = QLineF(colX, 0, colX, sheetRect.bottom());
painter->drawLine(line);
colX += colWidth;
}
}
qreal const rowHeight = layout->LayoutSettings().GetGridRowHeight();
if (rowHeight > 0)
{
qreal rowY = rowHeight;
while (rowY < sheetRect.bottom())
{
QLineF const line = QLineF(0, rowY, sheetRect.right(), rowY);
painter->drawLine(line);
rowY += rowHeight;
}
}
painter->restore();
}
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsSheet::FoldField(const QRectF &sheetRect) const -> QRectF
{
VPLayoutPtr const layout = m_layout.toStrongRef();
if (layout.isNull())
{
return sheetRect;
}
VPSheetPtr const sheet = layout->GetFocusedSheet();
qreal const xScale = layout->LayoutSettings().HorizontalScale();
qreal const yScale = layout->LayoutSettings().VerticalScale();
const int nbCol = layout->TileFactory()->ColNb(sheet);
const int nbRow = layout->TileFactory()->RowNb(sheet);
const qreal tilesWidth = (layout->TileFactory()->DrawingAreaWidth() - VPTileFactory::tileStripeWidth) / xScale;
const qreal tilesHeight = (layout->TileFactory()->DrawingAreaHeight() - VPTileFactory::tileStripeWidth) / yScale;
return {sheetRect.topLeft(), QSizeF(nbCol * tilesWidth, nbRow * tilesHeight)};
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsSheet::FoldText() -> QString
{
return tr("FOLD");
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsSheet::boundingRect() const -> QRectF
{
return GetSheetRect();
QRectF boundingRect = GetSheetRect();
VPLayoutPtr const layout = m_layout.toStrongRef();
if (not layout.isNull() && layout->LayoutSettings().IsCutOnFold())
{
QString const foldText = FoldText();
QFont font = QApplication::font();
font.setPointSize(foldFontSize);
QFontMetrics const metric(font);
QRectF textRect = metric.boundingRect(foldText);
QRectF const foldField = m_showBorder ? boundingRect : FoldField(GetMarginsRect());
if (boundingRect.width() >= boundingRect.height())
{
textRect.translate(foldField.center() - textRect.center());
textRect.translate(0, -(foldField.center().y() - foldField.topLeft().y()) - foldTextMargin -
textRect.height() / 2.);
boundingRect = foldField.united(textRect);
}
else
{
QRectF swappedRect = SwapRect(textRect);
swappedRect.translate(foldField.center() - swappedRect.center());
swappedRect.translate(
(foldField.topRight().x() - foldField.center().x()) + foldTextMargin + textRect.height() / 2., 0);
boundingRect = foldField.united(swappedRect);
}
}
return boundingRect;
}

View File

@ -29,6 +29,7 @@
#ifndef VPGRAPHICSSHEET_H
#define VPGRAPHICSSHEET_H
#include <QCoreApplication>
#include <QGraphicsItem>
#include <QPainter>
@ -41,6 +42,8 @@ class VPLayout;
class VPGraphicsSheet : public QGraphicsItem
{
Q_DECLARE_TR_FUNCTIONS(VPGraphicsSheet) // NOLINT
public:
explicit VPGraphicsSheet(const VPLayoutPtr &layout, QGraphicsItem *parent = nullptr);
~VPGraphicsSheet() override = default;
@ -65,6 +68,8 @@ public:
void RefreshBoundingRect();
static auto FoldText() -> QString;
private:
// cppcheck-suppress unknownMacro
Q_DISABLE_COPY_MOVE(VPGraphicsSheet) // NOLINT
@ -73,6 +78,16 @@ private:
bool m_showMargin{true};
bool m_showBorder{true};
void PaintVerticalFold(QPainter *painter, const QRectF &sheetRect) const;
void PaintHorizontalFold(QPainter *painter, const QRectF &sheetRect) const;
void PaintMargins(QPainter *painter) const;
void PaintBorder(QPainter *painter) const;
void PaintFold(QPainter *painter) const;
void PaintGrid(QPainter *painter) const;
auto FoldField(const QRectF &sheetRect) const -> QRectF;
};
#endif // VPGRAPHICSSHEET_H

View File

@ -147,7 +147,7 @@ void VPGraphicsTileGrid::paint(QPainter *painter, const QStyleOptionGraphicsItem
Q_UNUSED(widget);
Q_UNUSED(option);
VPLayoutPtr layout = m_layout.toStrongRef();
VPLayoutPtr const layout = m_layout.toStrongRef();
if (layout.isNull() || not layout->LayoutSettings().GetShowTiles())
{
return;
@ -157,14 +157,14 @@ void VPGraphicsTileGrid::paint(QPainter *painter, const QStyleOptionGraphicsItem
Qt::RoundJoin);
pen.setCosmetic(true);
pen.setStyle(Qt::DashLine);
QBrush noBrush(Qt::NoBrush);
QBrush const noBrush(Qt::NoBrush);
painter->setPen(pen);
painter->setBrush(noBrush);
qreal xScale = layout->LayoutSettings().HorizontalScale();
qreal yScale = layout->LayoutSettings().VerticalScale();
qreal const xScale = layout->LayoutSettings().HorizontalScale();
qreal const yScale = layout->LayoutSettings().VerticalScale();
VWatermarkData watermarkData = layout->TileFactory()->WatermarkData();
VWatermarkData const watermarkData = layout->TileFactory()->WatermarkData();
auto PaintWatermark = [painter, layout, xScale, yScale, watermarkData](const QRectF &img)
{
@ -187,13 +187,13 @@ void VPGraphicsTileGrid::paint(QPainter *painter, const QStyleOptionGraphicsItem
const qreal width = (layout->TileFactory()->DrawingAreaWidth() - VPTileFactory::tileStripeWidth) / xScale;
const qreal height = (layout->TileFactory()->DrawingAreaHeight() - VPTileFactory::tileStripeWidth) / yScale;
VPSheetPtr sheet = layout->GetSheet(m_sheetUuid);
QMarginsF sheetMargins = SheetMargins(sheet);
VPSheetPtr const sheet = layout->GetSheet(m_sheetUuid);
QMarginsF const sheetMargins = SheetMargins(sheet);
const int nbCol = layout->TileFactory()->ColNb(sheet);
const int nbRow = layout->TileFactory()->RowNb(sheet);
QFont font = OptimizeFontSizeToFitTextInRect(
QFont const font = OptimizeFontSizeToFitTextInRect(
painter, QRectF(sheetMargins.left(), sheetMargins.top(), width / 3., height / 3.),
QString::number(nbRow * nbCol));
@ -231,7 +231,7 @@ void VPGraphicsTileGrid::paint(QPainter *painter, const QStyleOptionGraphicsItem
if (j < nbRow && i < nbCol)
{
QRectF img(sheetMargins.left() + i * width, sheetMargins.top() + j * height, width, height);
QRectF const img(sheetMargins.left() + i * width, sheetMargins.top() + j * height, width, height);
PaintWatermark(img);
PaintTileNumber(img, i, j);

View File

@ -90,6 +90,11 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con
return;
}
if (VAbstractApplication::VApp()->IsWarningMessage(msg))
{
return;
}
// Why on earth didn't Qt want to make failed signal/slot connections qWarning?
if ((type == QtDebugMsg) && msg.contains(QStringLiteral("::connect")))
{

View File

@ -63,6 +63,8 @@
#include "dialogs/vpdialogabout.h"
#include "layout/vppiece.h"
#include "layout/vpsheet.h"
#include "scene/scenedef.h"
#include "scene/vpgraphicssheet.h"
#include "ui_vpmainwindow.h"
#include "undocommands/vpundoaddsheet.h"
#include "undocommands/vpundopiecemove.h"
@ -249,7 +251,7 @@ void SetPrinterTiledPageSettings(const QSharedPointer<QPrinter> &printer, const
return;
}
QSizeF tileSize = layout->LayoutSettings().GetTilesSize(Unit::Mm);
QSizeF const tileSize = layout->LayoutSettings().GetTilesSize(Unit::Mm);
QSizeF pageSize;
if (not forSheet)
@ -258,8 +260,8 @@ void SetPrinterTiledPageSettings(const QSharedPointer<QPrinter> &printer, const
}
else
{
QPageLayout::Orientation tileOrientation = layout->LayoutSettings().GetTilesOrientation();
QPageLayout::Orientation sheetOrientation = sheet->GetSheetOrientation();
QPageLayout::Orientation const tileOrientation = layout->LayoutSettings().GetTilesOrientation();
QPageLayout::Orientation const sheetOrientation = sheet->GetSheetOrientation();
if (tileOrientation != sheetOrientation)
{
@ -636,7 +638,6 @@ auto VPMainWindow::SaveLayout(const QString &path, QString &error) -> bool
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::ImportRawLayouts(const QStringList &rawLayouts)
{
for (const auto &path : rawLayouts)
{
if (not ImportRawLayout(path))
@ -782,6 +783,25 @@ void VPMainWindow::InitPropertyTabCurrentPiece()
}
});
connect(ui->checkBoxShowFullPiece, &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->IsShowFullPiece() != checked)
{
selectedPiece->SetShowFullPiece(checked);
LayoutWasSaved(false);
emit m_layout->PieceTransformationChanged(selectedPiece);
}
}
}
});
connect(ui->checkBoxCurrentPieceVerticallyFlipped, &QCheckBox::toggled, this,
[this](bool checked)
{
@ -1197,6 +1217,7 @@ void VPMainWindow::InitPropertyTabLayout()
&VPMainWindow::LayoutWarningPiecesSuperposition_toggled);
connect(ui->checkBoxLayoutWarningPiecesOutOfBound, &QCheckBox::toggled, this,
&VPMainWindow::LayoutWarningPiecesOutOfBound_toggled);
connect(ui->checkBoxCutOnFold, &QCheckBox::toggled, this, &VPMainWindow::LayoutCutOnFold_toggled);
connect(ui->checkBoxSheetStickyEdges, &QCheckBox::toggled, this,
[this](bool checked)
@ -1277,7 +1298,7 @@ void VPMainWindow::SetPropertiesData()
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::SetPropertyTabCurrentPieceData()
{
QList<VPPiecePtr> selectedPieces = SelectedPieces();
QList<VPPiecePtr> const selectedPieces = SelectedPieces();
ui->labelCurrentPieceNoPieceSelected->setVisible(false);
@ -1309,12 +1330,16 @@ void VPMainWindow::SetPropertyTabCurrentPieceData()
SetCheckBoxValue(ui->checkBoxCurrentPieceVerticallyFlipped, selectedPiece->IsVerticallyFlipped());
SetCheckBoxValue(ui->checkBoxCurrentPieceHorizontallyFlipped, selectedPiece->IsHorizontallyFlipped());
QLineF const seamMirrorLine = selectedPiece->GetSeamMirrorLine();
SetCheckBoxValue(ui->checkBoxShowFullPiece, !seamMirrorLine.isNull() ? selectedPiece->IsShowFullPiece() : true);
ui->checkBoxShowFullPiece->setEnabled(!seamMirrorLine.isNull());
const bool disableFlipping = selectedPiece->IsForbidFlipping() || selectedPiece->IsForceFlipping();
ui->checkBoxCurrentPieceVerticallyFlipped->setDisabled(disableFlipping);
if (not ui->checkBoxRelativeTranslation->isChecked())
{
QRectF rect = PiecesBoundingRect(selectedPieces);
QRectF const rect = PiecesBoundingRect(selectedPieces);
ui->doubleSpinBoxCurrentPieceBoxPositionX->setValue(
UnitConvertor(rect.topLeft().x(), Unit::Px, TranslateUnit()));
@ -1332,7 +1357,7 @@ void VPMainWindow::SetPropertyTabCurrentPieceData()
if (not ui->checkBoxRelativeTranslation->isChecked())
{
QRectF rect = PiecesBoundingRect(selectedPieces);
QRectF const rect = PiecesBoundingRect(selectedPieces);
ui->doubleSpinBoxCurrentPieceBoxPositionX->setValue(
UnitConvertor(rect.topLeft().x(), Unit::Px, TranslateUnit()));
@ -1546,6 +1571,7 @@ void VPMainWindow::SetPropertyTabLayoutData()
SetCheckBoxValue(ui->checkBoxSheetStickyEdges, m_layout->LayoutSettings().GetStickyEdges());
SetCheckBoxValue(ui->checkBoxFollowGainline, m_layout->LayoutSettings().GetFollowGrainline());
SetCheckBoxValue(ui->checkBoxTogetherWithNotches, m_layout->LayoutSettings().IsBoundaryTogetherWithNotches());
SetCheckBoxValue(ui->checkBoxCutOnFold, m_layout->LayoutSettings().IsCutOnFold());
// set pieces gap
SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetPiecesGap, m_layout->LayoutSettings().GetPiecesGapConverted());
@ -1583,6 +1609,7 @@ void VPMainWindow::SetPropertyTabLayoutData()
SetCheckBoxValue(ui->checkBoxSheetStickyEdges, false);
SetCheckBoxValue(ui->checkBoxFollowGainline, false);
SetCheckBoxValue(ui->checkBoxTogetherWithNotches, false);
SetCheckBoxValue(ui->checkBoxCutOnFold, false);
SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetPiecesGap, 0);
@ -2728,7 +2755,7 @@ void VPMainWindow::CleanWaterkmarkEditors()
QMutableListIterator<QPointer<WatermarkWindow>> i(m_watermarkEditors);
while (i.hasNext())
{
QPointer<WatermarkWindow> watermarkEditor = i.next();
QPointer<WatermarkWindow> const watermarkEditor = i.next();
if (watermarkEditor.isNull())
{
i.remove();
@ -2761,22 +2788,46 @@ auto VPMainWindow::DrawTilesScheme(QPrinter *printer, QPainter *painter, const V
sheet->SceneData()->PrepareTilesScheme();
qreal xScale = m_layout->LayoutSettings().HorizontalScale();
qreal yScale = m_layout->LayoutSettings().VerticalScale();
qreal const xScale = m_layout->LayoutSettings().HorizontalScale();
qreal const yScale = m_layout->LayoutSettings().VerticalScale();
qreal width = m_layout->TileFactory()->DrawingAreaWidth();
qreal height = m_layout->TileFactory()->DrawingAreaHeight();
qreal const width = m_layout->TileFactory()->DrawingAreaWidth();
qreal const height = m_layout->TileFactory()->DrawingAreaHeight();
QPageLayout::Orientation tileOrientation = m_layout->LayoutSettings().GetTilesOrientation();
QPageLayout::Orientation sheetOrientation = sheet->GetSheetOrientation();
QPageLayout::Orientation const tileOrientation = m_layout->LayoutSettings().GetTilesOrientation();
QPageLayout::Orientation const sheetOrientation = sheet->GetSheetOrientation();
QRectF sheetRect = sheet->GetMarginsRect();
QRectF const sheetRect = sheet->GetMarginsRect();
const int nbCol = m_layout->TileFactory()->ColNb(sheet);
const int nbRow = m_layout->TileFactory()->RowNb(sheet);
QRectF source = QRectF(sheetRect.topLeft(), QSizeF(nbCol * ((width - VPTileFactory::tileStripeWidth) / xScale),
nbRow * ((height - VPTileFactory::tileStripeWidth) / yScale)));
qreal const tilesWidth = nbCol * ((width - VPTileFactory::tileStripeWidth) / xScale);
qreal const tilesHeight = nbRow * ((height - VPTileFactory::tileStripeWidth) / yScale);
QRectF source;
if (m_layout->LayoutSettings().IsCutOnFold())
{
QFont font = QApplication::font();
font.setPointSize(foldFontSize);
QRectF const textRect = QFontMetrics(font).boundingRect(VPGraphicsSheet::FoldText());
qreal const textHeight = foldTextMargin + textRect.height();
if (sheet->GetSheetOrientation() == QPageLayout::Landscape)
{
QPointF const shift = QPointF(0, textHeight);
source = QRectF(sheetRect.topLeft() - shift, QSizeF(tilesWidth, tilesHeight + textHeight));
}
else
{
source = QRectF(sheetRect.topLeft(), QSizeF(tilesWidth + textHeight, tilesHeight));
}
}
else
{
source = QRectF(sheetRect.topLeft(), QSizeF(tilesWidth, tilesHeight));
}
QRectF target;
if (tileOrientation != sheetOrientation)
@ -2787,7 +2838,7 @@ auto VPMainWindow::DrawTilesScheme(QPrinter *printer, QPainter *painter, const V
margins = m_layout->LayoutSettings().GetTilesMargins();
}
QSizeF tilesSize = m_layout->LayoutSettings().GetTilesSize();
QSizeF const tilesSize = m_layout->LayoutSettings().GetTilesSize();
target = QRectF(0, 0, tilesSize.height() - margins.left() - margins.right(),
tilesSize.width() - margins.top() - margins.bottom());
}
@ -2800,7 +2851,7 @@ auto VPMainWindow::DrawTilesScheme(QPrinter *printer, QPainter *painter, const V
sheet->SceneData()->Scene()->render(painter, target, source, Qt::KeepAspectRatio);
VWatermarkData watermarkData = m_layout->TileFactory()->WatermarkData();
VWatermarkData const watermarkData = m_layout->TileFactory()->WatermarkData();
if (watermarkData.opacity > 0)
{
if (watermarkData.showImage && not watermarkData.path.isEmpty())
@ -4758,6 +4809,26 @@ void VPMainWindow::LayoutWarningPiecesOutOfBound_toggled(bool checked)
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::LayoutCutOnFold_toggled(bool checked)
{
if (not m_layout.isNull())
{
m_layout->LayoutSettings().SetCutOnFold(checked);
LayoutWasSaved(false);
if (checked)
{
VPSheetPtr const sheet = m_layout->GetFocusedSheet();
if (not sheet.isNull())
{
sheet->ValidatePiecesOutOfBound();
}
}
m_graphicsView->RefreshLayout();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::UpdateShortcuts()
{

View File

@ -294,6 +294,7 @@ private slots:
void LayoutWarningPiecesSuperposition_toggled(bool checked);
void LayoutWarningPiecesOutOfBound_toggled(bool checked);
void LayoutCutOnFold_toggled(bool checked);
void UpdateShortcuts();

View File

@ -219,7 +219,7 @@
<enum>QTabWidget::Rounded</enum>
</property>
<property name="currentIndex">
<number>0</number>
<number>1</number>
</property>
<property name="iconSize">
<size>
@ -280,7 +280,7 @@
<x>0</x>
<y>0</y>
<width>378</width>
<height>707</height>
<height>736</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_23">
@ -488,8 +488,7 @@
<string notr="true"/>
</property>
<property name="icon">
<iconset theme="object-rotate-right">
<normaloff>.</normaloff>.</iconset>
<iconset theme="object-rotate-right"/>
</property>
<property name="checkable">
<bool>true</bool>
@ -534,8 +533,7 @@
<string notr="true"/>
</property>
<property name="icon">
<iconset theme="object-rotate-left">
<normaloff>.</normaloff>.</iconset>
<iconset theme="object-rotate-left"/>
</property>
<property name="checkable">
<bool>true</bool>
@ -623,6 +621,19 @@
<string>Geometry</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<widget class="QCheckBox" name="checkBoxShowFullPiece">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Show full piece</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxCurrentPieceVerticallyFlipped">
<property name="text">
@ -1729,6 +1740,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxCutOnFold">
<property name="text">
<string>Cut on fold</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
@ -2013,8 +2031,7 @@
</widget>
<action name="actionOpen">
<property name="icon">
<iconset theme="document-open">
<normaloff>.</normaloff>.</iconset>
<iconset theme="document-open"/>
</property>
<property name="text">
<string>&amp;Open</string>
@ -2031,8 +2048,7 @@
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="document-save">
<normaloff>.</normaloff>.</iconset>
<iconset theme="document-save"/>
</property>
<property name="text">
<string>&amp;Save</string>
@ -2049,8 +2065,7 @@
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="document-save-as">
<normaloff>.</normaloff>.</iconset>
<iconset theme="document-save-as"/>
</property>
<property name="text">
<string>Save &amp;As</string>
@ -2078,8 +2093,7 @@
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="application-exit">
<normaloff>.</normaloff>.</iconset>
<iconset theme="application-exit"/>
</property>
<property name="text">
<string>E&amp;xit</string>
@ -2093,8 +2107,7 @@
</action>
<action name="actionNew">
<property name="icon">
<iconset theme="document-new">
<normaloff>.</normaloff>.</iconset>
<iconset theme="document-new"/>
</property>
<property name="text">
<string>&amp;New</string>
@ -2116,8 +2129,7 @@
</action>
<action name="actionAboutPuzzle">
<property name="icon">
<iconset theme="help-about">
<normaloff>.</normaloff>.</iconset>
<iconset theme="help-about"/>
</property>
<property name="text">
<string>About &amp;Puzzle</string>
@ -2148,8 +2160,7 @@
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="zoom-in">
<normaloff>.</normaloff>.</iconset>
<iconset theme="zoom-in"/>
</property>
<property name="text">
<string>Zoom in</string>
@ -2160,8 +2171,7 @@
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="zoom-out">
<normaloff>.</normaloff>.</iconset>
<iconset theme="zoom-out"/>
</property>
<property name="text">
<string>Zoom out</string>
@ -2172,8 +2182,7 @@
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="zoom-original">
<normaloff>.</normaloff>.</iconset>
<iconset theme="zoom-original"/>
</property>
<property name="text">
<string>Zoom 1:1</string>
@ -2184,8 +2193,7 @@
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="zoom-fit-best">
<normaloff>.</normaloff>.</iconset>
<iconset theme="zoom-fit-best"/>
</property>
<property name="text">
<string>Zoom fit best</string>
@ -2212,8 +2220,7 @@
</action>
<action name="actionPrintLayout">
<property name="icon">
<iconset theme="document-print">
<normaloff>.</normaloff>.</iconset>
<iconset theme="document-print"/>
</property>
<property name="text">
<string>Print</string>
@ -2224,8 +2231,7 @@
</action>
<action name="actionPrintPreviewLayout">
<property name="icon">
<iconset theme="document-print-preview">
<normaloff>.</normaloff>.</iconset>
<iconset theme="document-print-preview"/>
</property>
<property name="text">
<string>Print preview</string>
@ -2236,8 +2242,7 @@
</action>
<action name="actionPrintTiledLayout">
<property name="icon">
<iconset theme="document-print">
<normaloff>.</normaloff>.</iconset>
<iconset theme="document-print"/>
</property>
<property name="text">
<string>Print tiled</string>
@ -2248,8 +2253,7 @@
</action>
<action name="actionPrintPreviewTiledLayout">
<property name="icon">
<iconset theme="document-print-preview">
<normaloff>.</normaloff>.</iconset>
<iconset theme="document-print-preview"/>
</property>
<property name="text">
<string>Print preview tiled</string>
@ -2268,8 +2272,7 @@
</action>
<action name="actionPrintSheet">
<property name="icon">
<iconset theme="document-print">
<normaloff>.</normaloff>.</iconset>
<iconset theme="document-print"/>
</property>
<property name="text">
<string>Print</string>
@ -2280,8 +2283,7 @@
</action>
<action name="actionPrintPreviewSheet">
<property name="icon">
<iconset theme="document-print-preview">
<normaloff>.</normaloff>.</iconset>
<iconset theme="document-print-preview"/>
</property>
<property name="text">
<string>Print preview</string>
@ -2292,8 +2294,7 @@
</action>
<action name="actionPrintTiledSheet">
<property name="icon">
<iconset theme="document-print">
<normaloff>.</normaloff>.</iconset>
<iconset theme="document-print"/>
</property>
<property name="text">
<string>Print tiled</string>
@ -2304,8 +2305,7 @@
</action>
<action name="actionPrintPreviewTiledSheet">
<property name="icon">
<iconset theme="document-print-preview">
<normaloff>.</normaloff>.</iconset>
<iconset theme="document-print-preview"/>
</property>
<property name="text">
<string>Print preview tiled</string>
@ -2324,8 +2324,7 @@
</action>
<action name="actionWatermarkEditor">
<property name="icon">
<iconset theme="document-new">
<normaloff>.</normaloff>.</iconset>
<iconset theme="document-new"/>
</property>
<property name="text">
<string>Editor</string>
@ -2353,8 +2352,7 @@
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="document-open">
<normaloff>.</normaloff>.</iconset>
<iconset theme="document-open"/>
</property>
<property name="text">
<string>Load</string>
@ -2368,8 +2366,7 @@
<bool>false</bool>
</property>
<property name="icon">
<iconset theme="edit-delete">
<normaloff>.</normaloff>.</iconset>
<iconset theme="edit-delete"/>
</property>
<property name="text">
<string>Remove</string>
@ -2380,8 +2377,7 @@
</action>
<action name="actionZValueBottom">
<property name="icon">
<iconset theme="go-bottom">
<normaloff>.</normaloff>.</iconset>
<iconset theme="go-bottom"/>
</property>
<property name="text">
<string>Bottom</string>
@ -2389,8 +2385,7 @@
</action>
<action name="actionZValueDown">
<property name="icon">
<iconset theme="go-down">
<normaloff>.</normaloff>.</iconset>
<iconset theme="go-down"/>
</property>
<property name="text">
<string>Down</string>
@ -2398,8 +2393,7 @@
</action>
<action name="actionZValueUp">
<property name="icon">
<iconset theme="go-up">
<normaloff>.</normaloff>.</iconset>
<iconset theme="go-up"/>
</property>
<property name="text">
<string>Up</string>
@ -2407,8 +2401,7 @@
</action>
<action name="actionZValueTop">
<property name="icon">
<iconset theme="go-top">
<normaloff>.</normaloff>.</iconset>
<iconset theme="go-top"/>
</property>
<property name="text">
<string>Top</string>
@ -2441,8 +2434,8 @@
</resources>
<connections/>
<buttongroups>
<buttongroup name="buttonGroupRotationDirection"/>
<buttongroup name="buttonGroupSheetOrientation"/>
<buttongroup name="buttonGroupRotationDirection"/>
<buttongroup name="buttonGroupTileOrientation"/>
</buttongroups>
</ui>

View File

@ -343,6 +343,7 @@ void VPLayoutFileReader::ReadControl(const VPLayoutPtr &layout)
layout->LayoutSettings().SetFollowGrainline(ReadAttributeBool(attribs, ML::AttrFollowGrainline, falseStr));
layout->LayoutSettings().SetBoundaryTogetherWithNotches(
ReadAttributeBool(attribs, ML::AttrBoundaryTogetherWithNotches, falseStr));
layout->LayoutSettings().SetCutOnFold(ReadAttributeBool(attribs, ML::AttrCutOnFold, falseStr));
readElementText();
}
@ -518,6 +519,7 @@ void VPLayoutFileReader::ReadPiece(const VPPiecePtr &piece)
piece->SetFollowGrainline(ReadAttributeBool(attribs, ML::AttrFollowGrainline, falseStr));
piece->SetSewLineOnDrawing(ReadAttributeBool(attribs, ML::AttrSewLineOnDrawing, falseStr));
piece->SetMatrix(StringToTransfrom(ReadAttributeEmptyString(attribs, ML::AttrTransform)));
piece->SetShowFullPiece(ReadAttributeBool(attribs, ML::AttrShowFullPiece, trueStr));
const QStringList tags{
ML::TagSeamLine, // 0
@ -526,7 +528,8 @@ void VPLayoutFileReader::ReadPiece(const VPPiecePtr &piece)
ML::TagNotches, // 3
ML::TagInternalPaths, // 4
ML::TagMarkers, // 5
ML::TagLabels // 6
ML::TagLabels, // 6
ML::TagMirrorLine // 7
};
while (readNextStartElement())
@ -554,6 +557,9 @@ void VPLayoutFileReader::ReadPiece(const VPPiecePtr &piece)
case 6: // labels
ReadLabels(piece);
break;
case 7: // mirror line
ReadMirrorLines(piece);
break;
default:
qCDebug(MLReader, "Ignoring tag %s", qUtf8Printable(name().toString()));
skipCurrentElement();
@ -738,11 +744,12 @@ auto VPLayoutFileReader::ReadInternalPath() -> VLayoutPiecePath
VLayoutPiecePath path;
QXmlStreamAttributes attribs = attributes();
QXmlStreamAttributes const attribs = attributes();
path.SetCutPath(ReadAttributeBool(attribs, ML::AttrCut, falseStr));
path.SetPenStyle(LineStyleToPenStyle(ReadAttributeString(attribs, ML::AttrPenStyle, TypeLineLine)));
path.SetNotMirrored(ReadAttributeBool(attribs, ML::AttrNotMirrored, falseStr));
QVector<VLayoutPoint> shape = ReadLayoutPoints();
QVector<VLayoutPoint> const shape = ReadLayoutPoints();
if (shape.isEmpty())
{
throw VException(tr("Error in line %1. Internal path shape is empty.").arg(lineNumber()));
@ -786,14 +793,15 @@ auto VPLayoutFileReader::ReadMarker() -> VLayoutPlaceLabel
VLayoutPlaceLabel marker;
QXmlStreamAttributes attribs = attributes();
QXmlStreamAttributes const attribs = attributes();
QString matrix = ReadAttributeEmptyString(attribs, ML::AttrTransform);
QString const matrix = ReadAttributeEmptyString(attribs, ML::AttrTransform);
marker.SetRotationMatrix(StringToTransfrom(matrix));
marker.SetType(static_cast<PlaceLabelType>(ReadAttributeUInt(attribs, ML::AttrType, QChar('0'))));
marker.SetCenter(StringToPoint(ReadAttributeEmptyString(attribs, ML::AttrCenter)));
marker.SetBox(StringToRect(ReadAttributeEmptyString(attribs, ML::AttrBox)));
marker.SetNotMirrored(ReadAttributeBool(attribs, ML::AttrNotMirrored, falseStr));
// cppcheck-suppress unknownMacro
QT_WARNING_POP
@ -940,6 +948,54 @@ void VPLayoutFileReader::ReadWatermark(const VPLayoutPtr &layout)
layout->LayoutSettings().SetWatermarkPath(readElementText());
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutFileReader::ReadMirrorLines(const VPPiecePtr &piece)
{
AssertRootTag(ML::TagMirrorLine);
QXmlStreamAttributes const attribs = attributes();
piece->SetFoldLineType(StringToFoldLineType(
ReadAttributeString(attribs, ML::AttrGrainlineType, FoldLineTypeToString(FoldLineType::TwoArrowsTextAbove))));
piece->SetFoldLineHeight(ReadAttributeDouble(attribs, ML::AttrFoldLineHeight, QChar('0')));
piece->SetFoldLineWidth(ReadAttributeDouble(attribs, ML::AttrFoldLineWidth, QChar('0')));
piece->SetFoldLineCenterPosition(ReadAttributeDouble(attribs, ML::AttrFoldLineCenter, QString::number(0.5)));
piece->SetFoldLineLabelFontBold(ReadAttributeBool(attribs, ML::AttrBold, falseStr));
piece->SetFoldLineLabelFontItalic(ReadAttributeBool(attribs, ML::AttrItalic, falseStr));
piece->SetFoldLineLabelAlignment(
ReadAttributeInt(attribs, ML::AttrAlignment, QString::number(static_cast<int>(Qt::AlignHCenter))));
piece->SetFoldLineLabel(ReadAttributeEmptyString(attribs, ML::AttrFoldLineLabel));
piece->SetFoldLineOutlineFont(FontFromString(ReadAttributeEmptyString(attribs, ML::AttrFont)));
QStringList const svgFontData = ReadAttributeEmptyString(attribs, ML::AttrSVGFont).split(','_L1);
if (!svgFontData.isEmpty())
{
piece->SetFoldLineSVGFontFamily(svgFontData.constFirst());
if (svgFontData.size() > 1)
{
piece->SetFoldLineSvgFontSize(svgFontData.at(1).toUInt());
}
}
while (readNextStartElement())
{
if (name() == ML::TagSeamLine)
{
piece->SetSeamMirrorLine(StringToLine(readElementText()));
}
else if (name() == ML::TagSeamAllowance)
{
piece->SetSeamAllowanceMirrorLine(StringToLine(readElementText()));
}
else
{
qCDebug(MLReader, "Ignoring tag %s", qUtf8Printable(name().toString()));
skipCurrentElement();
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutFileReader::ReadLayoutMargins(const VPLayoutPtr &layout)
{

View File

@ -29,9 +29,9 @@
#ifndef VPLAYOUTFILEREADER_H
#define VPLAYOUTFILEREADER_H
#include <QXmlStreamReader>
#include "../ifc/xml/vabstractconverter.h"
#include "../layout/layoutdef.h"
#include <QXmlStreamReader>
#include <QLoggingCategory>
@ -47,6 +47,7 @@ class VLayoutPoint;
class VPLayoutFileReader : public QXmlStreamReader
{
Q_DECLARE_TR_FUNCTIONS(VPLayoutFileReader) // NOLINT
public:
VPLayoutFileReader() = default;
~VPLayoutFileReader() = default;
@ -84,7 +85,7 @@ private:
auto ReadLabelLines() -> VTextManager;
auto ReadLabelLine() -> TextLine;
void ReadWatermark(const VPLayoutPtr &layout);
void ReadMirrorLines(const VPPiecePtr &piece);
void ReadLayoutMargins(const VPLayoutPtr &layout);
void ReadSheetMargins(const VPSheetPtr &sheet);
@ -92,17 +93,17 @@ private:
void AssertRootTag(const QString &tag) const;
static auto ReadAttributeString(const QXmlStreamAttributes &attribs, const QString &name,
const QString &defValue) -> QString;
static auto ReadAttributeString(const QXmlStreamAttributes &attribs, const QString &name, const QString &defValue)
-> QString;
static auto ReadAttributeEmptyString(const QXmlStreamAttributes &attribs, const QString &name) -> QString;
static auto ReadAttributeBool(const QXmlStreamAttributes &attribs, const QString &name,
const QString &defValue) -> bool;
static auto ReadAttributeDouble(const QXmlStreamAttributes &attribs, const QString &name,
const QString &defValue) -> qreal;
static auto ReadAttributeUInt(const QXmlStreamAttributes &attribs, const QString &name,
const QString &defValue) -> quint32;
static auto ReadAttributeInt(const QXmlStreamAttributes &attribs, const QString &name,
const QString &defValue) -> int;
static auto ReadAttributeBool(const QXmlStreamAttributes &attribs, const QString &name, const QString &defValue)
-> bool;
static auto ReadAttributeDouble(const QXmlStreamAttributes &attribs, const QString &name, const QString &defValue)
-> qreal;
static auto ReadAttributeUInt(const QXmlStreamAttributes &attribs, const QString &name, const QString &defValue)
-> quint32;
static auto ReadAttributeInt(const QXmlStreamAttributes &attribs, const QString &name, const QString &defValue)
-> int;
};
#endif // VPLAYOUTFILEREADER_H

View File

@ -35,6 +35,8 @@
#include "../vlayout/vlayoutpiecepath.h"
#include "../vlayout/vtextmanager.h"
#include "../vmisc/projectversion.h"
#include "def.h"
#include "qnumeric.h"
#include "vplayoutliterals.h"
namespace
@ -174,6 +176,8 @@ void VPLayoutFileWriter::WriteLayoutProperties(const VPLayoutPtr &layout)
SetAttribute(ML::AttrPiecesGap, layout->LayoutSettings().GetPiecesGap());
SetAttribute(ML::AttrFollowGrainline, layout->LayoutSettings().GetFollowGrainline());
SetAttribute(ML::AttrBoundaryTogetherWithNotches, layout->LayoutSettings().IsBoundaryTogetherWithNotches());
SetAttributeOrRemoveIf<bool>(ML::AttrCutOnFold, layout->LayoutSettings().IsCutOnFold(),
[](bool cut) noexcept { return not cut; });
writeEndElement(); // control
WriteTiles(layout);
@ -284,6 +288,8 @@ void VPLayoutFileWriter::WritePiece(const VPPiecePtr &piece)
[](qreal ys) noexcept { return VFuzzyComparePossibleNulls(ys, 1.0); });
SetAttributeOrRemoveIf<qreal>(ML::AttrZValue, piece->ZValue(),
[](qreal z) noexcept { return VFuzzyComparePossibleNulls(z, 1.0); });
SetAttributeOrRemoveIf<bool>(ML::AttrShowFullPiece, piece->IsShowFullPiece(),
[](bool show) noexcept { return show; });
writeStartElement(ML::TagSeamLine);
QVector<VLayoutPoint> contourPoints = piece->GetContourPoints();
@ -340,6 +346,8 @@ void VPLayoutFileWriter::WritePiece(const VPPiecePtr &piece)
writeStartElement(ML::TagInternalPath);
SetAttribute(ML::AttrCut, path.IsCutPath());
SetAttribute(ML::AttrPenStyle, PenStyleToLineStyle(path.PenStyle()));
SetAttributeOrRemoveIf<bool>(ML::AttrNotMirrored, path.IsNotMirrored(),
[](bool mirrored) noexcept { return mirrored; });
QVector<VLayoutPoint> points = path.Points();
for (auto &point : points)
@ -360,6 +368,8 @@ void VPLayoutFileWriter::WritePiece(const VPPiecePtr &piece)
SetAttribute(ML::AttrType, static_cast<int>(label.Type()));
SetAttribute(ML::AttrCenter, PointToString(label.Center()));
SetAttribute(ML::AttrBox, RectToString(label.Box()));
SetAttributeOrRemoveIf<bool>(ML::AttrNotMirrored, label.IsNotMirrored(),
[](bool mirrored) noexcept { return mirrored; });
writeEndElement();
}
writeEndElement();
@ -369,6 +379,51 @@ void VPLayoutFileWriter::WritePiece(const VPPiecePtr &piece)
WriteLabel(piece->GetPatternLabelRect(), piece->GetPatternLabelData(), ML::TagPatternLabel);
writeEndElement();
QLineF const seamMirrorLine = piece->GetSeamMirrorLine();
QLineF const seamAllowenceMirrorLine = piece->GetSeamAllowanceMirrorLine();
if (!seamMirrorLine.isNull() || !seamAllowenceMirrorLine.isNull())
{
writeStartElement(ML::TagMirrorLine);
SetAttribute(ML::AttrFoldLineType, FoldLineTypeToString(piece->GetFoldLineType()));
SetAttributeOrRemoveIf<qreal>(ML::AttrFoldLineHeight, piece->GetFoldLineHeight(),
[](qreal height) noexcept { return qFuzzyIsNull(height); });
SetAttributeOrRemoveIf<qreal>(ML::AttrFoldLineWidth, piece->GetFoldLineWidth(),
[](qreal width) noexcept { return qFuzzyIsNull(width); });
SetAttributeOrRemoveIf<qreal>(ML::AttrFoldLineCenter, piece->GetFoldLineCenterPosition(),
[](qreal center) noexcept { return VFuzzyComparePossibleNulls(center, 0.5); });
SetAttributeOrRemoveIf<bool>(ML::AttrItalic, piece->IsFoldLineLabelFontItalic(),
[](bool italic) noexcept { return not italic; });
SetAttributeOrRemoveIf<bool>(ML::AttrBold, piece->IsFoldLineLabelFontBold(),
[](bool bold) noexcept { return not bold; });
SetAttributeOrRemoveIf<QString>(ML::AttrFoldLineLabel, piece->GetFoldLineLabel(),
[](const QString &label) noexcept { return label.isEmpty(); });
SetAttributeOrRemoveIf<int>(ML::AttrAlignment, piece->GetFoldLineLabelAlignment(),
[](int alignment) noexcept { return alignment == Qt::AlignHCenter; });
SetAttributeOrRemoveIf<QString>(ML::AttrFont, piece->GetFoldLineOutlineFont().toString(),
[piece](const QString &) { return piece->GetFoldLineLabel().isEmpty(); });
SetAttributeOrRemoveIf<QString>(
ML::AttrSVGFont,
QStringLiteral("%1,%2").arg(piece->GetFoldLineSVGFontFamily()).arg(piece->GetFoldLineSvgFontSize()),
[piece](const QString &) { return piece->GetFoldLineLabel().isEmpty(); });
if (!seamMirrorLine.isNull())
{
writeStartElement(ML::TagSeamLine);
writeCharacters(LineToString(seamMirrorLine));
writeEndElement();
}
if (!seamAllowenceMirrorLine.isNull())
{
writeStartElement(ML::TagSeamAllowance);
writeCharacters(LineToString(seamAllowenceMirrorLine));
writeEndElement();
}
writeEndElement();
}
writeEndElement();
}
@ -389,7 +444,7 @@ void VPLayoutFileWriter::WriteLabelLines(const VTextManager &tm)
{
writeStartElement(ML::TagLines);
SetAttribute(ML::AttrFont, tm.GetFont().toString());
SetAttribute(ML::AttrSVGFont, QStringLiteral("%1,%2").arg(tm.GetSVGFontFamily(), tm.GetSVGFontPointSize()));
SetAttribute(ML::AttrSVGFont, QStringLiteral("%1,%2").arg(tm.GetSVGFontFamily()).arg(tm.GetSVGFontPointSize()));
for (int i = 0; i < tm.GetSourceLinesCount(); ++i)
{

View File

@ -67,6 +67,7 @@ const QString TagLine = QStringLiteral("line"); // NOLINT(ce
const QString TagScale = QStringLiteral("scale"); // NOLINT(cert-err58-cpp)
const QString TagWatermark = QStringLiteral("watermark"); // NOLINT(cert-err58-cpp)
const QString TagPoint = QStringLiteral("point"); // NOLINT(cert-err58-cpp)
const QString TagMirrorLine = QStringLiteral("mirrorLine"); // NOLINT(cert-err58-cpp)
const QString AttrWarningSuperposition = QStringLiteral("warningSuperposition"); // NOLINT(cert-err58-cpp)
const QString AttrWarningOutOfBound = QStringLiteral("warningOutOfBound"); // NOLINT(cert-err58-cpp)
@ -123,6 +124,14 @@ const QString AttrY = QStringLiteral("y");
const QString AttrTurnPoint = QStringLiteral("turnPoint"); // NOLINT(cert-err58-cpp)
const QString AttrCurvePoint = QStringLiteral("curvePoint"); // NOLINT(cert-err58-cpp)
const QString AttrClockwiseOpening = QStringLiteral("clockwiseOpening"); // NOLINT(cert-err58-cpp)
const QString AttrShowFullPiece = QStringLiteral("showFullPiece"); // NOLINT(cert-err58-cpp)
const QString AttrNotMirrored = QStringLiteral("notMirrored"); // NOLINT(cert-err58-cpp)
const QString AttrCutOnFold = QStringLiteral("cutOnFold"); // NOLINT(cert-err58-cpp)
const QString AttrFoldLineType = QStringLiteral("type"); // NOLINT(cert-err58-cpp)
const QString AttrFoldLineHeight = QStringLiteral("height"); // NOLINT(cert-err58-cpp)
const QString AttrFoldLineWidth = QStringLiteral("width"); // NOLINT(cert-err58-cpp)
const QString AttrFoldLineCenter = QStringLiteral("center"); // NOLINT(cert-err58-cpp)
const QString AttrFoldLineLabel = QStringLiteral("label"); // NOLINT(cert-err58-cpp)
const QString oneWayUpStr = QStringLiteral("oneWayUp"); // NOLINT(cert-err58-cpp)
const QString oneWayDownStr = QStringLiteral("oneWayDown"); // NOLINT(cert-err58-cpp)

View File

@ -66,6 +66,7 @@ extern const QString TagLine;
extern const QString TagScale;
extern const QString TagWatermark;
extern const QString TagPoint;
extern const QString TagMirrorLine;
extern const QString AttrWarningSuperposition;
extern const QString AttrWarningOutOfBound;
@ -122,6 +123,14 @@ extern const QString AttrY;
extern const QString AttrTurnPoint;
extern const QString AttrCurvePoint;
extern const QString AttrClockwiseOpening;
extern const QString AttrShowFullPiece;
extern const QString AttrNotMirrored;
extern const QString AttrCutOnFold;
extern const QString AttrFoldLineType;
extern const QString AttrFoldLineHeight;
extern const QString AttrFoldLineWidth;
extern const QString AttrFoldLineCenter;
extern const QString AttrFoldLineLabel;
extern const QString oneWayUpStr;
extern const QString oneWayDownStr;

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<pattern labelPrefix="uk">
<!--Pattern created with Valentina v0.7.52.902 (https://smart-pattern.com.ua/).-->
<version>0.9.4</version>
<unit>cm</unit>
<description/>
<notes/>
<measurements/>
<increments/>
<previewCalculations/>
<draw name="Pattern piece 1">
<calculation>
<point id="1" mx="0.264583" my="0.396875" name="А" showLabel="true" type="single" x="0.79375" y="1.05833"/>
<point angle="270" basePoint="1" id="2" length="15" lineColor="black" mx="0.264583" my="0.396875" name="А1" showLabel="true" type="endLine" typeLine="hair"/>
<point angle="0" basePoint="1" id="3" length="20" lineColor="black" mx="0.264583" my="0.396875" name="А2" showLabel="true" type="endLine" typeLine="hair"/>
<point angle="270" basePoint="3" id="4" length="10" lineColor="black" mx="0.264583" my="0.396875" name="А3" showLabel="true" type="endLine" typeLine="hair"/>
<line firstPoint="2" id="5" lineColor="black" secondPoint="4" typeLine="hair"/>
</calculation>
<modeling>
<point id="10" idObject="1" inUse="false" mx="0.264583" my="0.396875" showLabel="true" type="modeling"/>
<point id="11" idObject="3" inUse="false" mx="0.264583" my="0.396875" showLabel="true" type="modeling"/>
<point id="12" idObject="4" inUse="false" mx="0.264583" my="0.396875" showLabel="true" type="modeling"/>
<point id="13" idObject="2" inUse="false" mx="0.264583" my="0.396875" showLabel="true" type="modeling"/>
<point id="15" idObject="1" inUse="false" mx="0.264583" my="0.396875" showLabel="true" type="modeling"/>
<point id="16" idObject="3" inUse="false" mx="0.264583" my="0.396875" showLabel="true" type="modeling"/>
<point id="17" idObject="4" inUse="false" mx="0.264583" my="0.396875" showLabel="true" type="modeling"/>
<point id="18" idObject="2" inUse="false" mx="0.264583" my="0.396875" showLabel="true" type="modeling"/>
<point id="20" idObject="1" inUse="true" mx="0.264583" my="0.396875" showLabel="true" type="modeling"/>
<point id="21" idObject="3" inUse="true" mx="0.264583" my="0.396875" showLabel="true" type="modeling"/>
<point id="22" idObject="4" inUse="true" mx="0.264583" my="0.396875" showLabel="true" type="modeling"/>
<point id="23" idObject="2" inUse="true" mx="0.264583" my="0.396875" showLabel="true" type="modeling"/>
<point id="25" idObject="1" inUse="true" mx="0.264583" my="0.396875" showLabel="true" type="modeling"/>
<point id="26" idObject="3" inUse="true" mx="0.264583" my="0.396875" showLabel="true" type="modeling"/>
<point id="27" idObject="4" inUse="true" mx="0.264583" my="0.396875" showLabel="true" type="modeling"/>
<point id="28" idObject="2" inUse="true" mx="0.264583" my="0.396875" showLabel="true" type="modeling"/>
</modeling>
<details>
<detail followGrainline="false" forbidFlipping="false" forceFlipping="false" hideMainPath="false" id="14" mx="0" my="0" name="Case 1" seamAllowance="true" sewLineOnDrawing="false" uuid="{410acde1-f2f0-4603-89e9-f2569843673b}" version="2" width="1">
<data annotation="" foldPosition="" height="10" letter="" mx="0" my="0" onFold="false" orientation="" quantity="1" rotation="0" rotationWay="" tilt="" visible="false" width="10"/>
<patternInfo height="10" mx="0" my="0" rotation="0" visible="false" width="10"/>
<grainline arrows="0" length="10" mx="0" my="0" rotation="90" visible="false"/>
<nodes>
<node idObject="10" type="NodePoint"/>
<node idObject="11" type="NodePoint"/>
<node idObject="12" type="NodePoint"/>
<node idObject="13" type="NodePoint"/>
</nodes>
<mirrorLine fontSize="6" p1="12" p2="13" type="none"/>
</detail>
<detail followGrainline="false" forbidFlipping="false" forceFlipping="false" hideMainPath="false" id="19" mx="31.0026" my="-0.303098" name="Case 2" seamAllowance="true" sewLineOnDrawing="false" uuid="{5ce7b61f-1d49-4ef3-8922-521b9aac6b49}" version="2" width="1">
<data annotation="" foldPosition="" height="10" letter="" mx="0" my="0" onFold="false" orientation="" quantity="1" rotation="0" rotationWay="" tilt="" visible="false" width="10"/>
<patternInfo height="10" mx="0" my="0" rotation="0" visible="false" width="10"/>
<grainline arrows="0" length="10" mx="0" my="0" rotation="90" visible="false"/>
<nodes>
<node idObject="16" type="NodePoint"/>
<node idObject="17" type="NodePoint"/>
<node idObject="18" type="NodePoint"/>
<node idObject="15" type="NodePoint"/>
</nodes>
<mirrorLine fontSize="6" p1="17" p2="18" type="none"/>
</detail>
<detail followGrainline="false" forbidFlipping="false" forceFlipping="false" hideMainPath="false" id="24" mx="66.2511" my="-0.29709" name="Case 3" seamAllowance="true" sewLineOnDrawing="false" uuid="{cce244ba-8361-44ef-841a-dea47de205c7}" version="2" width="1">
<data annotation="" foldPosition="" height="10" letter="" mx="0" my="0" onFold="false" orientation="" quantity="1" rotation="0" rotationWay="" tilt="" visible="false" width="10"/>
<patternInfo height="10" mx="0" my="0" rotation="0" visible="false" width="10"/>
<grainline arrows="0" length="10" mx="0" my="0" rotation="90" visible="false"/>
<nodes>
<node idObject="22" type="NodePoint"/>
<node idObject="23" type="NodePoint"/>
<node idObject="20" type="NodePoint"/>
<node idObject="21" type="NodePoint"/>
</nodes>
<mirrorLine fontSize="6" p1="22" p2="23" type="none"/>
</detail>
<detail followGrainline="false" forbidFlipping="false" forceFlipping="false" hideMainPath="false" id="29" mx="101.666" my="0" name="Case 4" seamAllowance="true" sewLineOnDrawing="false" uuid="{c73f153b-9a1a-4a09-9117-b4b8ab4808a7}" version="2" width="1">
<data annotation="" foldPosition="" height="10" letter="" mx="0" my="0" onFold="false" orientation="" quantity="1" rotation="0" rotationWay="" tilt="" visible="false" width="10"/>
<patternInfo height="10" mx="0" my="0" rotation="0" visible="false" width="10"/>
<grainline arrows="0" length="10" mx="0" my="0" rotation="90" visible="false"/>
<nodes>
<node idObject="28" type="NodePoint"/>
<node idObject="25" type="NodePoint"/>
<node idObject="26" type="NodePoint"/>
<node idObject="27" type="NodePoint"/>
</nodes>
<mirrorLine fontSize="6" p1="27" p2="28" type="none"/>
</detail>
</details>
<groups/>
</draw>
</pattern>

View File

@ -2850,8 +2850,8 @@ void VToolOptionsPropertyBrowser::ShowOptionsToolTrueDarts(QGraphicsItem *item)
AddPropertyParentPointName(i->BaseLineP1Name(), tr("First base point:"), AttrFirstPoint);
AddPropertyParentPointName(i->BaseLineP2Name(), tr("Second base point:"), AttrSecondPoint);
AddPropertyParentPointName(i->DartP1Name(), tr("First dart point:"), AttrDartP1);
AddPropertyParentPointName(i->DartP2Name(), tr("First dart point:"), AttrDartP2);
AddPropertyParentPointName(i->DartP3Name(), tr("First dart point:"), AttrDartP3);
AddPropertyParentPointName(i->DartP2Name(), tr("Second dart point:"), AttrDartP2);
AddPropertyParentPointName(i->DartP3Name(), tr("Third dart point:"), AttrDartP3);
AddPropertyText(tr("Notes:"), i->GetNotes(), AttrNotes);
}

View File

@ -323,7 +323,7 @@ void PreferencesPatternPage::InitLabelFontSizes()
ui->comboBoxLabelFontSize->clear();
// Get the available font sizes
QList<int> sizes = QFontDatabase::standardSizes();
QList<int> const sizes = QFontDatabase::standardSizes();
for (auto size : sizes)
{
if (size >= VCommonSettings::MinPieceLabelFontPointSize())

View File

@ -126,7 +126,6 @@ DialogSaveLayout::DialogSaveLayout(int count, Draw mode, const QString &fileName
else
{
RemoveFormatFromList(LayoutExportFormats::RLD);
ui->checkBoxTextAsPaths->setVisible(false);
}
connect(bOk, &QPushButton::clicked, this, &DialogSaveLayout::Save);
@ -439,9 +438,12 @@ void DialogSaveLayout::ShowExample()
ui->labelOptionsNotAvailable->setVisible(false);
ui->checkBoxBinaryDXF->setVisible(false);
ui->checkBoxTextAsPaths->setVisible(false);
ui->checkBoxTextAsPaths->setEnabled(true);
ui->checkBoxShowGrainline->setVisible(false);
ui->checkBoxTogetherWithNotches->setVisible(false);
VCommonSettings *settings = VAbstractApplication::VApp()->Settings();
switch (currentFormat)
{
case LayoutExportFormats::DXF_AAMA:
@ -452,7 +454,12 @@ void DialogSaveLayout::ShowExample()
case LayoutExportFormats::PDFTiled:
ui->groupBoxPaperFormat->setEnabled(true);
ui->groupBoxMargins->setEnabled(true);
ui->checkBoxTextAsPaths->setVisible(m_mode != Draw::Layout);
ui->checkBoxTextAsPaths->setVisible(true);
if (settings->GetSingleLineFonts() || settings->GetSingleStrokeOutlineFont())
{
ui->checkBoxTextAsPaths->setDisabled(true);
ui->checkBoxTextAsPaths->setChecked(true);
}
ui->checkBoxShowGrainline->setVisible(true);
ui->checkBoxTogetherWithNotches->setVisible(m_mode != Draw::Layout);
break;
@ -463,11 +470,16 @@ void DialogSaveLayout::ShowExample()
break;
case LayoutExportFormats::SVG:
case LayoutExportFormats::PDF:
case LayoutExportFormats::PNG:
case LayoutExportFormats::PS:
case LayoutExportFormats::EPS:
case LayoutExportFormats::PNG:
case LayoutExportFormats::TIF:
ui->checkBoxTextAsPaths->setVisible(m_mode != Draw::Layout);
ui->checkBoxTextAsPaths->setVisible(true);
if (settings->GetSingleLineFonts() || settings->GetSingleStrokeOutlineFont())
{
ui->checkBoxTextAsPaths->setDisabled(true);
ui->checkBoxTextAsPaths->setChecked(true);
}
ui->checkBoxShowGrainline->setVisible(true);
ui->checkBoxTogetherWithNotches->setVisible(m_mode != Draw::Layout);
break;
@ -481,7 +493,12 @@ void DialogSaveLayout::ShowExample()
case LayoutExportFormats::DXF_AC1024_Flat:
case LayoutExportFormats::DXF_AC1027_Flat:
ui->checkBoxBinaryDXF->setVisible(true);
ui->checkBoxTextAsPaths->setVisible(m_mode != Draw::Layout);
ui->checkBoxTextAsPaths->setVisible(true);
if (settings->GetSingleLineFonts() || settings->GetSingleStrokeOutlineFont())
{
ui->checkBoxTextAsPaths->setDisabled(true);
ui->checkBoxTextAsPaths->setChecked(true);
}
ui->checkBoxShowGrainline->setVisible(true);
ui->checkBoxTogetherWithNotches->setVisible(m_mode != Draw::Layout);
break;
@ -532,16 +549,9 @@ auto DialogSaveLayout::IsTextAsPaths() const -> bool
//---------------------------------------------------------------------------------------------------------------------
void DialogSaveLayout::SetTextAsPaths(bool textAsPaths)
{
if (m_mode != Draw::Layout)
{
ui->checkBoxTextAsPaths->setChecked(textAsPaths);
}
else
{
ui->checkBoxTextAsPaths->setChecked(false);
}
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSaveLayout::SetTiledExportMode(bool tiledExportMode)

View File

@ -138,7 +138,7 @@
<string>Show grainline</string>
</property>
<property name="checked">
<bool>false</bool>
<bool>true</bool>
</property>
</widget>
</item>

View File

@ -4274,7 +4274,12 @@ void MainWindow::on_actionCreateManualLayout_triggered()
DialogLayoutScale layoutScale(false, this);
layoutScale.SetXScale(1);
layoutScale.SetYScale(1);
layoutScale.exec();
int const res = layoutScale.exec();
if (res == QDialog::Rejected)
{
return;
}
VLayoutExporter exporter;
exporter.SetFileName(rldFile.fileName());

View File

@ -33,6 +33,7 @@
#include "../ifc/exception/vexceptionobjecterror.h"
#include "../ifc/exception/vexceptionundo.h"
#include "../ifc/exception/vexceptionwrongid.h"
#include "../ifc/ifcdef.h"
#include "../ifc/xml/vpatternconverter.h"
#include "../qmuparser/qmuparsererror.h"
#include "../qmuparser/qmutokenparser.h"
@ -43,6 +44,7 @@
#include "../vgeometry/vsplinepath.h"
#include "../vmisc/compatibility.h"
#include "../vmisc/customevents.h"
#include "../vmisc/def.h"
#include "../vmisc/projectversion.h"
#include "../vmisc/vsysexits.h"
#include "../vmisc/vvalentinasettings.h"
@ -54,11 +56,6 @@
#include "../vpatterndb/vnodedetail.h"
#include "../vpatterndb/vpiecenode.h"
#include "../vpatterndb/vpiecepath.h"
#include "../vtools/tools/vdatatool.h"
#include "../vtools/tools/vtoolseamallowance.h"
#include "../vtools/tools/vtooluniondetails.h"
#include "../vwidgets/vabstractmainwindow.h"
#include "../vtools/tools/drawTools/operation/flipping/vtoolflippingbyaxis.h"
#include "../vtools/tools/drawTools/operation/flipping/vtoolflippingbyline.h"
#include "../vtools/tools/drawTools/operation/vtoolmove.h"
@ -93,7 +90,6 @@
#include "../vtools/tools/drawTools/toolpoint/toolsinglepoint/vtoolpointofintersectioncurves.h"
#include "../vtools/tools/drawTools/toolpoint/toolsinglepoint/vtooltriangle.h"
#include "../vtools/tools/drawTools/vtoolline.h"
#include "../vtools/tools/nodeDetails/vnodearc.h"
#include "../vtools/tools/nodeDetails/vnodeellipticalarc.h"
#include "../vtools/tools/nodeDetails/vnodepoint.h"
@ -102,6 +98,11 @@
#include "../vtools/tools/nodeDetails/vtoolpiecepath.h"
#include "../vtools/tools/nodeDetails/vtoolpin.h"
#include "../vtools/tools/nodeDetails/vtoolplacelabel.h"
#include "../vtools/tools/vdatatool.h"
#include "../vtools/tools/vtoolseamallowance.h"
#include "../vtools/tools/vtooluniondetails.h"
#include "../vwidgets/vabstractmainwindow.h"
#include "qminmax.h"
#if QT_VERSION < QT_VERSION_CHECK(5, 12, 0)
#include "../vmisc/backport/qscopeguard.h"
@ -161,6 +162,51 @@ auto DefLabelLanguage() -> QString
}
return def;
}
struct VPieceFoldLineData
{
quint32 p1{NULL_ID};
quint32 p2{NULL_ID};
QString heightFormula{};
QString widthFormula{};
QString centerFormula{};
bool manualHeight{false};
bool manualWidth{false};
bool manualCenter{false};
FoldLineType type{FoldLineType::TwoArrowsTextAbove};
unsigned int fontSize{defFoldLineFontSize};
bool italic{false};
bool bold{false};
QString label{};
int alignment{Qt::AlignHCenter};
};
//---------------------------------------------------------------------------------------------------------------------
auto ParsePieceMirrorLine(const QDomElement &domElement) -> VPieceFoldLineData
{
VPieceFoldLineData data;
data.p1 = VDomDocument::GetParametrUInt(domElement, VAbstractPattern::AttrMirrorLineP1, NULL_ID_STR);
data.p2 = VDomDocument::GetParametrUInt(domElement, VAbstractPattern::AttrMirrorLineP2, NULL_ID_STR);
data.heightFormula = VDomDocument::GetParametrEmptyString(domElement, VAbstractPattern::AttrFoldLineHeightFormula);
data.widthFormula = VDomDocument::GetParametrEmptyString(domElement, VAbstractPattern::AttrFoldLineWidthFormula);
data.centerFormula = VDomDocument::GetParametrEmptyString(domElement, VAbstractPattern::AttrFoldLineCenterFormula);
data.manualHeight = VDomDocument::GetParametrBool(domElement, VAbstractPattern::AttrFoldLineManualHeight, falseStr);
data.manualWidth = VDomDocument::GetParametrBool(domElement, VAbstractPattern::AttrFoldLineManualWidth, falseStr);
data.manualCenter = VDomDocument::GetParametrBool(domElement, VAbstractPattern::AttrFoldLineManualCenter, falseStr);
data.type = StringToFoldLineType(VDomDocument::GetParametrString(
domElement, VAbstractPattern::AttrFoldLineType, FoldLineTypeToString(FoldLineType::TwoArrowsTextAbove)));
data.fontSize = qMax(static_cast<unsigned int>(VCommonSettings::MinPieceLabelFontPointSize()),
VDomDocument::GetParametrUInt(domElement, VAbstractPattern::AttrFoldLineFontSize,
QString::number(defFoldLineFontSize)));
data.italic = VDomDocument::GetParametrBool(domElement, VDomDocument::AttrItalic, falseStr);
data.bold = VDomDocument::GetParametrBool(domElement, VDomDocument::AttrBold, falseStr);
data.label = VDomDocument::GetParametrEmptyString(domElement, VAbstractPattern::AttrFoldLineLabel);
data.alignment =
VDomDocument::GetParametrInt(domElement, VDomDocument::AttrAlignment, QString::number(Qt::AlignHCenter));
return data;
}
} // anonymous namespace
//---------------------------------------------------------------------------------------------------------------------
@ -956,6 +1002,7 @@ void VPattern::ParseDetailElement(QDomElement &domElement, const Document &parse
initData.detail.SetHideMainPath(
GetParametrBool(domElement, VToolSeamAllowance::AttrHideMainPath,
QString().setNum(VAbstractValApplication::VApp()->ValentinaSettings()->IsHideMainPath())));
initData.detail.SetShowFullPiece(GetParametrBool(domElement, VToolSeamAllowance::AttrShowFullPiece, trueStr));
initData.detail.SetSeamAllowanceBuiltIn(
GetParametrBool(domElement, VToolSeamAllowance::AttrSeamAllowanceBuiltIn, falseStr));
initData.detail.SetForbidFlipping(GetParametrBool(
@ -1009,9 +1056,15 @@ void VPattern::ParseDetailInternals(const QDomElement &domElement, VPiece &detai
{
const uint version = GetParametrUInt(domElement, AttrVersion, QChar('1'));
const QStringList tags = QStringList() << TagNodes << TagData << TagPatternInfo << TagGrainline
<< VToolSeamAllowance::TagCSA << VToolSeamAllowance::TagIPaths
<< VToolSeamAllowance::TagPins << VToolSeamAllowance::TagPlaceLabels;
const QStringList tags{TagNodes,
TagData,
TagPatternInfo,
TagGrainline,
VToolSeamAllowance::TagCSA,
VToolSeamAllowance::TagIPaths,
VToolSeamAllowance::TagPins,
VToolSeamAllowance::TagPlaceLabels,
VToolSeamAllowance::TagMirrorLine};
QFuture<QVector<VPieceNode>> futurePathV1;
QFuture<VPiecePath> futurePathV2;
@ -1022,6 +1075,7 @@ void VPattern::ParseDetailInternals(const QDomElement &domElement, VPiece &detai
QFuture<QVector<quint32>> futureIPaths;
QFuture<QVector<quint32>> futurePins;
QFuture<QVector<quint32>> futurePlaceLabels;
QFuture<VPieceFoldLineData> futureMirrorLine;
const QDomNodeList nodeList = domElement.childNodes();
for (qint32 i = 0; i < nodeList.size(); ++i)
@ -1076,6 +1130,9 @@ void VPattern::ParseDetailInternals(const QDomElement &domElement, VPiece &detai
case 7: // VToolSeamAllowance::TagPlaceLabels
futurePlaceLabels = QtConcurrent::run(&VPattern::ParsePiecePointRecords, element);
break;
case 8: // VToolSeamAllowance::TagMirrorLine
futureMirrorLine = QtConcurrent::run(&ParsePieceMirrorLine, element);
break;
default:
break;
}
@ -1125,6 +1182,25 @@ void VPattern::ParseDetailInternals(const QDomElement &domElement, VPiece &detai
{
detail.SetPlaceLabels(futurePlaceLabels.result());
}
if (not futureMirrorLine.isCanceled())
{
VPieceFoldLineData const data = futureMirrorLine.result();
detail.SetMirrorLineStartPoint(data.p1);
detail.SetMirrorLineEndPoint(data.p2);
detail.SetManualFoldHeight(data.manualHeight);
detail.SetManualFoldWidth(data.manualWidth);
detail.SetManualFoldCenter(data.manualCenter);
detail.SetFormulaFoldHeight(data.heightFormula);
detail.SetFormulaFoldWidth(data.widthFormula);
detail.SetFormulaFoldCenter(data.centerFormula);
detail.SetFoldLineType(data.type);
detail.SetFoldLineSvgFontSize(data.fontSize);
detail.SetFoldLineLabelFontItalic(data.italic);
detail.SetFoldLineLabelFontBold(data.bold);
detail.SetFoldLineLabel(data.label);
detail.SetFoldLineLabelAlignment(data.alignment);
}
}
//---------------------------------------------------------------------------------------------------------------------
@ -2042,6 +2118,8 @@ void VPattern::ParsePlaceLabel(QDomElement &domElement, const Document &parse)
initData.type = static_cast<PlaceLabelType>(GetParametrUInt(domElement, AttrPlaceLabelType, QChar('0')));
initData.notMirrored = GetParametrBool(domElement, AttrNotMirrored, falseStr);
VToolPlaceLabel::Create(initData);
// Rewrite attribute formula. Need for situation when we have wrong formula.
@ -4096,6 +4174,7 @@ void VPattern::ParsePathElement(VMainGraphicsScene *scene, QDomElement &domEleme
initData.path.SetFirstToCuttingContour(GetParametrBool(domElement, AttrFirstToContour, falseStr));
initData.path.SetLastToCuttingContour(GetParametrBool(domElement, AttrLastToContour, falseStr));
initData.path.SetVisibilityTrigger(GetParametrString(domElement, AttrVisible, QChar('1')));
initData.path.SetNotMirrored(GetParametrBool(domElement, AttrNotMirrored, falseStr));
}
VToolPiecePath::Create(initData);

View File

@ -149,6 +149,7 @@ const QString AttrCurve2Alias1 = QStringLiteral("curve2Alias1");
const QString AttrCurve2Alias2 = QStringLiteral("curve2Alias2");
const QString AttrLayoutVersion = QStringLiteral("version");
const QString AttrKMVersion = QStringLiteral("version");
const QString AttrNotMirrored = QStringLiteral("notMirrored");
const QString TypeLineDefault = QStringLiteral("default");
const QString TypeLineNone = QStringLiteral("none");

View File

@ -166,6 +166,7 @@ extern const QString AttrCurve2Alias1;
extern const QString AttrCurve2Alias2;
extern const QString AttrLayoutVersion;
extern const QString AttrKMVersion;
extern const QString AttrNotMirrored;
extern const QString TypeLineDefault;
extern const QString TypeLineNone;

View File

@ -69,6 +69,7 @@
<file>schema/pattern/v0.9.1.xsd</file>
<file>schema/pattern/v0.9.2.xsd</file>
<file>schema/pattern/v0.9.3.xsd</file>
<file>schema/pattern/v0.9.4.xsd</file>
<file>schema/multisize_measurements/v0.3.0.xsd</file>
<file>schema/multisize_measurements/v0.4.0.xsd</file>
<file>schema/multisize_measurements/v0.4.1.xsd</file>
@ -104,6 +105,7 @@
<file>schema/layout/v0.1.5.xsd</file>
<file>schema/layout/v0.1.6.xsd</file>
<file>schema/layout/v0.1.7.xsd</file>
<file>schema/layout/v0.1.8.xsd</file>
<file>schema/known_measurements/v1.0.0.xsd</file>
</qresource>
</RCC>

View File

@ -0,0 +1,646 @@
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="layout">
<xs:complexType>
<xs:sequence>
<xs:element name="properties">
<xs:complexType>
<xs:sequence>
<xs:element type="units" name="unit"/>
<xs:element type="xs:string" name="title"/>
<xs:element type="xs:string" name="description"/>
<xs:element name="control">
<xs:complexType>
<xs:attribute type="xs:boolean" name="warningSuperposition"/>
<xs:attribute type="xs:boolean" name="warningOutOfBound"/>
<xs:attribute type="xs:boolean" name="stickyEdges"/>
<xs:attribute type="xs:boolean" name="followGrainline"/>
<xs:attribute type="xs:boolean" name="boundaryTogetherWithNotches"/>
<xs:attribute type="xs:float" name="piecesGap"/>
<xs:attribute type="xs:boolean" name="cutOnFold"/>
</xs:complexType>
</xs:element>
<xs:element name="tiles">
<xs:complexType>
<xs:sequence>
<xs:element name="size">
<xs:complexType>
<xs:attribute type="xs:float" name="width" use="required"/>
<xs:attribute type="xs:float" name="length" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="margin">
<xs:complexType>
<xs:attribute type="xs:float" name="top"/>
<xs:attribute type="xs:float" name="right"/>
<xs:attribute type="xs:float" name="bottom"/>
<xs:attribute type="xs:float" name="left"/>
<xs:attribute type="xs:boolean" name="ignoreMargins"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:boolean" name="visible"/>
<xs:attribute type="xs:string" name="matchingMarks"/>
<xs:attribute type="xs:boolean" name="printScheme"/>
<xs:attribute type="xs:boolean" name="tileNumber"/>
</xs:complexType>
</xs:element>
<xs:element name="scale">
<xs:complexType>
<xs:attribute type="LayoutScale" name="xScale"/>
<xs:attribute type="LayoutScale" name="yScale"/>
</xs:complexType>
</xs:element>
<xs:element name="watermark">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:boolean" name="showPreview" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="unplacedPieces">
<xs:complexType>
<xs:sequence>
<xs:element name="piece" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="seamLine">
<xs:complexType>
<xs:sequence>
<xs:element name="point" minOccurs="3" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:double" name="x" use="required"/>
<xs:attribute type="xs:double" name="y" use="required"/>
<xs:attribute type="xs:boolean" name="turnPoint" use="optional"/>
<xs:attribute type="xs:boolean" name="curvePoint" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="seamAllowance">
<xs:complexType>
<xs:sequence>
<xs:element name="point" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:double" name="x" use="required"/>
<xs:attribute type="xs:double" name="y" use="required"/>
<xs:attribute type="xs:boolean" name="turnPoint" use="optional"/>
<xs:attribute type="xs:boolean" name="curvePoint" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:boolean" name="enabled" use="optional"/>
<xs:attribute type="xs:boolean" name="builtIn" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="grainline">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="LinePathOrEmpty">
<xs:attribute type="xs:boolean" name="enabled" use="optional"/>
<xs:attribute type="ArrowDirection" name="arrowDirection" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="notches">
<xs:complexType>
<xs:sequence>
<xs:element name="notch" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:boolean" name="builtIn" use="optional"/>
<xs:attribute type="NotchType" name="type" use="optional"/>
<xs:attribute type="LinePath" name="baseLine" use="optional"/>
<xs:attribute type="LinesPath" name="path" use="optional"/>
<xs:attribute type="xs:boolean" name="clockwiseOpening" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="internalPaths">
<xs:complexType>
<xs:sequence>
<xs:element name="internalPath" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="point" minOccurs="2" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:double" name="x" use="required"/>
<xs:attribute type="xs:double" name="y" use="required"/>
<xs:attribute type="xs:boolean" name="turnPoint" use="optional"/>
<xs:attribute type="xs:boolean" name="curvePoint" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:boolean" name="cut" use="optional"/>
<xs:attribute type="CurvePenStyle" name="penStyle" use="optional"/>
<xs:attribute type="xs:boolean" name="notMirrored" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="markers">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element name="marker" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:attribute type="Transformation" name="transform" use="required"/>
<xs:attribute type="MarkerType" name="type" use="required"/>
<xs:attribute type="PointPath" name="center" use="required"/>
<xs:attribute type="RectPath" name="box" use="required"/>
<xs:attribute type="xs:boolean" name="notMirrored" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="labels">
<xs:complexType>
<xs:sequence>
<xs:element name="pieceLabel" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="lines">
<xs:complexType>
<xs:sequence>
<xs:element name="line" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:boolean" name="bold" use="optional"/>
<xs:attribute type="xs:boolean" name="italic" use="optional"/>
<xs:attribute type="xs:unsignedInt" name="alignment" use="optional"/>
<xs:attribute type="xs:unsignedInt" name="fontSize" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="font"/>
<xs:attribute type="xs:string" name="svgFont"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="shape" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="patternLabel" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="lines">
<xs:complexType>
<xs:sequence>
<xs:element name="line" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:boolean" name="bold" use="optional"/>
<xs:attribute type="xs:boolean" name="italic" use="optional"/>
<xs:attribute type="xs:unsignedInt" name="alignment" use="optional"/>
<xs:attribute type="xs:unsignedInt" name="fontSize" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="font"/>
<xs:attribute type="xs:string" name="svgFont"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="shape" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="mirrorLine" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element type="LinePathOrEmpty" name="seamLine"/>
<xs:element type="LinePathOrEmpty" name="seamAllowance"/>
</xs:sequence>
<xs:attribute name="type" type="foldLineType" use="optional"/>
<xs:attribute name="height" type="xs:double" use="optional"/>
<xs:attribute name="width" type="xs:double" use="optional"/>
<xs:attribute name="center" type="xs:double" use="optional"/>
<xs:attribute type="xs:boolean" name="bold" use="optional"/>
<xs:attribute type="xs:boolean" name="italic" use="optional"/>
<xs:attribute type="AlignmentType" name="alignment" use="optional"/>
<xs:attribute name="label" type="xs:string" use="optional"/>
<xs:attribute type="xs:string" name="font" use="optional"/>
<xs:attribute type="xs:string" name="svgFont" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="uid" type="uuid" use="required"/>
<xs:attribute type="xs:string" name="name"/>
<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"/>
<xs:attribute type="xs:boolean" name="sewLineOnDrawing"/>
<xs:attribute type="Transformation" name="transform"/>
<xs:attribute type="xs:string" name="gradationLabel"/>
<xs:attribute type="xs:unsignedInt" name="copyNumber"/>
<xs:attribute type="xs:boolean" name="showSeamline"/>
<xs:attribute type="xs:float" name="xScale"/>
<xs:attribute type="xs:float" name="yScale"/>
<xs:attribute type="xs:boolean" name="showFullPiece"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="sheets">
<xs:complexType>
<xs:sequence>
<xs:element name="sheet" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="name"/>
<xs:element name="size">
<xs:complexType>
<xs:attribute type="xs:float" name="width" use="required"/>
<xs:attribute type="xs:float" name="length" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="margin">
<xs:complexType>
<xs:attribute type="xs:float" name="top"/>
<xs:attribute type="xs:float" name="right"/>
<xs:attribute type="xs:float" name="bottom"/>
<xs:attribute type="xs:float" name="left"/>
<xs:attribute type="xs:boolean" name="ignoreMargins"/>
</xs:complexType>
</xs:element>
<xs:element name="pieces">
<xs:complexType>
<xs:sequence>
<xs:element name="piece" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="seamLine">
<xs:complexType>
<xs:sequence>
<xs:element name="point" minOccurs="3" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:double" name="x" use="required"/>
<xs:attribute type="xs:double" name="y" use="required"/>
<xs:attribute type="xs:boolean" name="turnPoint" use="optional"/>
<xs:attribute type="xs:boolean" name="curvePoint" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="seamAllowance">
<xs:complexType>
<xs:sequence>
<xs:element name="point" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:double" name="x" use="required"/>
<xs:attribute type="xs:double" name="y" use="required"/>
<xs:attribute type="xs:boolean" name="turnPoint" use="optional"/>
<xs:attribute type="xs:boolean" name="curvePoint" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:boolean" name="enabled" use="optional"/>
<xs:attribute type="xs:boolean" name="builtIn" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="grainline">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="LinePathOrEmpty">
<xs:attribute type="xs:boolean" name="enabled" use="optional"/>
<xs:attribute type="ArrowDirection" name="arrowDirection" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="notches">
<xs:complexType>
<xs:sequence>
<xs:element name="notch" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:boolean" name="builtIn" use="optional"/>
<xs:attribute type="NotchType" name="type" use="optional"/>
<xs:attribute type="LinePath" name="baseLine" use="optional"/>
<xs:attribute type="LinesPath" name="path" use="optional"/>
<xs:attribute type="xs:boolean" name="clockwiseOpening" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="internalPaths">
<xs:complexType>
<xs:sequence>
<xs:element name="internalPath" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="point" minOccurs="2" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:double" name="x" use="required"/>
<xs:attribute type="xs:double" name="y" use="required"/>
<xs:attribute type="xs:boolean" name="turnPoint" use="optional"/>
<xs:attribute type="xs:boolean" name="curvePoint" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:boolean" name="cut" use="optional"/>
<xs:attribute type="CurvePenStyle" name="penStyle" use="optional"/>
<xs:attribute type="xs:boolean" name="notMirrored" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="markers">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element name="marker" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:attribute type="Transformation" name="transform" use="required"/>
<xs:attribute type="MarkerType" name="type" use="required"/>
<xs:attribute type="PointPath" name="center" use="required"/>
<xs:attribute type="RectPath" name="box" use="required"/>
<xs:attribute type="xs:boolean" name="notMirrored" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="labels">
<xs:complexType>
<xs:sequence>
<xs:element name="pieceLabel" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="lines">
<xs:complexType>
<xs:sequence>
<xs:element name="line" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:boolean" name="bold" use="optional"/>
<xs:attribute type="xs:boolean" name="italic" use="optional"/>
<xs:attribute type="AlignmentType" name="alignment" use="optional"/>
<xs:attribute type="xs:unsignedInt" name="fontSize" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="font"/>
<xs:attribute type="xs:string" name="svgFont"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="PathNotEmpty" name="shape" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="patternLabel" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="lines">
<xs:complexType>
<xs:sequence>
<xs:element name="line" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:boolean" name="bold" use="optional"/>
<xs:attribute type="xs:boolean" name="italic" use="optional"/>
<xs:attribute type="AlignmentType" name="alignment" use="optional"/>
<xs:attribute type="xs:unsignedInt" name="fontSize" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="font"/>
<xs:attribute type="xs:string" name="svgFont"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="PathNotEmpty" name="shape" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="mirrorLine" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element type="LinePathOrEmpty" name="seamLine"/>
<xs:element type="LinePathOrEmpty" name="seamAllowance"/>
</xs:sequence>
<xs:attribute name="type" type="foldLineType" use="optional"/>
<xs:attribute name="height" type="xs:double" use="optional"/>
<xs:attribute name="width" type="xs:double" use="optional"/>
<xs:attribute name="center" type="xs:double" use="optional"/>
<xs:attribute type="xs:boolean" name="bold" use="optional"/>
<xs:attribute type="xs:boolean" name="italic" use="optional"/>
<xs:attribute type="AlignmentType" name="alignment" use="optional"/>
<xs:attribute name="label" type="xs:string" use="optional"/>
<xs:attribute type="xs:string" name="font" use="optional"/>
<xs:attribute type="xs:string" name="svgFont" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="uid" type="uuid" use="required"/>
<xs:attribute type="xs:string" name="name"/>
<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"/>
<xs:attribute type="xs:boolean" name="sewLineOnDrawing"/>
<xs:attribute type="Transformation" name="transform"/>
<xs:attribute type="xs:string" name="gradationLabel"/>
<xs:attribute type="xs:unsignedInt" name="copyNumber"/>
<xs:attribute type="xs:boolean" name="showSeamline"/>
<xs:attribute type="xs:float" name="xScale"/>
<xs:attribute type="xs:float" name="yScale"/>
<xs:attribute type="xs:float" name="zValue"/>
<xs:attribute type="xs:boolean" name="showFullPiece"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="GrainlineType" name="grainlineType"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="formatVersion" name="version" use="required"/>
</xs:complexType>
</xs:element>
<!--Types-->
<xs:simpleType name="formatVersion">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9]{1,}\.[0-9]{1,}\.[0-9]{1,}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="units">
<xs:restriction base="xs:string">
<xs:enumeration value="mm"/>
<xs:enumeration value="cm"/>
<xs:enumeration value="inch"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="uuid">
<xs:restriction base="xs:string">
<xs:pattern value="|\{[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}\}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="ArrowDirection">
<xs:restriction base="xs:string">
<xs:enumeration value="oneWayUp"/>
<xs:enumeration value="oneWayDown"/>
<xs:enumeration value="twoWaysUpDown"/>
<xs:enumeration value="fourWays"/>
<xs:enumeration value="twoWaysUpLeft"/>
<xs:enumeration value="twoWaysUpRight"/>
<xs:enumeration value="twoWaysDownLeft"/>
<xs:enumeration value="twoWaysDownRight"/>
<xs:enumeration value="threeWaysUpDownLeft"/>
<xs:enumeration value="threeWaysUpDownRight"/>
<xs:enumeration value="threeWaysUpLeftRight"/>
<xs:enumeration value="threeWaysDownLeftRight"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="NotchType">
<xs:restriction base="xs:unsignedInt">
<!--OneLine-->
<xs:enumeration value="0"/>
<!--TwoLines-->
<xs:enumeration value="1"/>
<!--ThreeLines-->
<xs:enumeration value="2"/>
<!--TMark-->
<xs:enumeration value="3"/>
<!--VMark-->
<xs:enumeration value="4"/>
<!--VMark2-->
<xs:enumeration value="5"/>
<!--UMark-->
<xs:enumeration value="6"/>
<!--BoxMark-->
<xs:enumeration value="7"/>
<!--CheckMark-->
<xs:enumeration value="8"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="CurvePenStyle">
<xs:restriction base="xs:string">
<xs:enumeration value="hair"/>
<xs:enumeration value="dashLine"/>
<xs:enumeration value="dotLine"/>
<xs:enumeration value="dashDotLine"/>
<xs:enumeration value="dashDotDotLine"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="MarkerType">
<xs:restriction base="xs:unsignedInt">
<xs:enumeration value="0"/><!--Segment-->
<xs:enumeration value="1"/><!--Rectangle-->
<xs:enumeration value="2"/><!--Cross-->
<xs:enumeration value="3"/><!--Tshaped-->
<xs:enumeration value="4"/><!--Doubletree-->
<xs:enumeration value="5"/><!--Corner-->
<xs:enumeration value="6"/><!--Triangle-->
<xs:enumeration value="7"/><!--Hshaped-->
<xs:enumeration value="8"/><!--Button-->
<xs:enumeration value="9"/><!--Circle-->
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="AlignmentType">
<xs:restriction base="xs:unsignedInt">
<xs:enumeration value="0"/><!--default (no aligns)-->
<xs:enumeration value="1"/><!--aligns with the left edge-->
<xs:enumeration value="2"/><!--aligns with the right edge-->
<xs:enumeration value="4"/><!--Centers horizontally in the available space-->
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="Transformation">
<xs:restriction base="xs:string">
<xs:pattern value="([-+]?\d+\.?\d*([eE][-+]?\d+)?;){8,}[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="PathNotEmpty">
<xs:restriction base="xs:string">
<xs:pattern value="([-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?\s){0,}[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="PathOrEmpty">
<xs:restriction base="xs:string">
<xs:pattern value="|([-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?\s){0,}[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="LinePathOrEmpty">
<xs:restriction base="xs:string">
<xs:pattern value="|[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?;[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="LinePath">
<xs:restriction base="xs:string">
<xs:pattern value="[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?;[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="LinesPath">
<xs:restriction base="xs:string">
<xs:pattern value="([-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?;[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?\*){0,}[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?;[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="PointPath">
<xs:restriction base="xs:string">
<xs:pattern value="[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="RectPath">
<xs:restriction base="xs:string">
<xs:pattern value="([-+]?\d+\.?\d*([eE][-+]?\d+)?;){3,}[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="GrainlineType">
<xs:restriction base="xs:string">
<xs:enumeration value="horizontal"/>
<xs:enumeration value="vertical"/>
<xs:enumeration value="notFixed"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="LayoutScale">
<xs:restriction base="xs:float">
<xs:minInclusive value="0.01"/>
<xs:maxInclusive value="3"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="foldLineType">
<xs:restriction base="xs:string">
<xs:enumeration value="2ArrowsTextAbove"/><!--Same as default-->
<xs:enumeration value="2ArrowsTextUnder"/>
<xs:enumeration value="2Arrows"/>
<xs:enumeration value="text"/>
<xs:enumeration value="3dots"/>
<xs:enumeration value="3X"/>
<xs:enumeration value="none"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>

File diff suppressed because it is too large Load Diff

View File

@ -155,6 +155,17 @@ const QString VAbstractPattern::AttrImageId = QStringLiteral("imageId");
const QString VAbstractPattern::AttrDimensionA = QStringLiteral("dimensionA");
const QString VAbstractPattern::AttrDimensionB = QStringLiteral("dimensionB");
const QString VAbstractPattern::AttrDimensionC = QStringLiteral("dimensionC");
const QString VAbstractPattern::AttrMirrorLineP1 = QStringLiteral("p1");
const QString VAbstractPattern::AttrMirrorLineP2 = QStringLiteral("p2");
const QString VAbstractPattern::AttrFoldLineHeightFormula = QStringLiteral("height");
const QString VAbstractPattern::AttrFoldLineWidthFormula = QStringLiteral("width");
const QString VAbstractPattern::AttrFoldLineCenterFormula = QStringLiteral("center");
const QString VAbstractPattern::AttrFoldLineManualHeight = QStringLiteral("manualHeight");
const QString VAbstractPattern::AttrFoldLineManualWidth = QStringLiteral("manualWidth");
const QString VAbstractPattern::AttrFoldLineManualCenter = QStringLiteral("manualCenter");
const QString VAbstractPattern::AttrFoldLineType = QStringLiteral("type");
const QString VAbstractPattern::AttrFoldLineFontSize = QStringLiteral("fontSize");
const QString VAbstractPattern::AttrFoldLineLabel = QStringLiteral("label");
const QString VAbstractPattern::AttrContentType = QStringLiteral("contentType");
@ -764,8 +775,9 @@ auto VAbstractPattern::ParsePieceInternalPaths(const QDomElement &domElement) ->
//---------------------------------------------------------------------------------------------------------------------
auto VAbstractPattern::ParsePiecePointRecords(const QDomElement &domElement) -> QVector<quint32>
{
QVector<quint32> records;
const QDomNodeList nodeList = domElement.childNodes();
QVector<quint32> records;
records.reserve(nodeList.size());
for (qint32 i = 0; i < nodeList.size(); ++i)
{
const QDomElement element = nodeList.at(i).toElement();

View File

@ -382,6 +382,17 @@ public:
static const QString AttrDimensionA;
static const QString AttrDimensionB;
static const QString AttrDimensionC;
static const QString AttrMirrorLineP1;
static const QString AttrMirrorLineP2;
static const QString AttrFoldLineHeightFormula;
static const QString AttrFoldLineWidthFormula;
static const QString AttrFoldLineCenterFormula;
static const QString AttrFoldLineManualHeight;
static const QString AttrFoldLineManualWidth;
static const QString AttrFoldLineManualCenter;
static const QString AttrFoldLineType;
static const QString AttrFoldLineFontSize;
static const QString AttrFoldLineLabel;
static const QString AttrContentType;

View File

@ -45,8 +45,8 @@ using namespace Qt::Literals::StringLiterals;
*/
const QString VLayoutConverter::LayoutMinVerStr = QStringLiteral("0.1.0");
const QString VLayoutConverter::LayoutMaxVerStr = QStringLiteral("0.1.7");
const QString VLayoutConverter::CurrentSchema = QStringLiteral("://schema/layout/v0.1.7.xsd");
const QString VLayoutConverter::LayoutMaxVerStr = QStringLiteral("0.1.8");
const QString VLayoutConverter::CurrentSchema = QStringLiteral("://schema/layout/v0.1.8.xsd");
// VLayoutConverter::LayoutMinVer; // <== DON'T FORGET TO UPDATE TOO!!!!
// VLayoutConverter::LayoutMaxVer; // <== DON'T FORGET TO UPDATE TOO!!!!
@ -151,7 +151,8 @@ auto VLayoutConverter::XSDSchemas() -> QHash<unsigned int, QString>
std::make_pair(FormatVersion(0, 1, 4), QStringLiteral("://schema/layout/v0.1.4.xsd")),
std::make_pair(FormatVersion(0, 1, 5), QStringLiteral("://schema/layout/v0.1.5.xsd")),
std::make_pair(FormatVersion(0, 1, 6), QStringLiteral("://schema/layout/v0.1.6.xsd")),
std::make_pair(FormatVersion(0, 1, 7), CurrentSchema),
std::make_pair(FormatVersion(0, 1, 7), QStringLiteral("://schema/layout/v0.1.7.xsd")),
std::make_pair(FormatVersion(0, 1, 8), CurrentSchema),
};
return schemas;
@ -190,9 +191,12 @@ void VLayoutConverter::ApplyPatches()
case (FormatVersion(0, 1, 5)):
case (FormatVersion(0, 1, 6)):
ToV0_1_7();
ValidateXML(CurrentSchema);
Q_FALLTHROUGH();
case (FormatVersion(0, 1, 7)):
ToV0_1_8();
ValidateXML(CurrentSchema);
Q_FALLTHROUGH();
case (FormatVersion(0, 1, 8)):
break;
default:
InvalidVersion(m_ver);
@ -431,3 +435,13 @@ void VLayoutConverter::ToV0_1_7()
SetVersion(QStringLiteral("0.1.7"));
Save();
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutConverter::ToV0_1_8()
{
// TODO. Delete if minimal supported version is 0.1.8
Q_STATIC_ASSERT_X(VLayoutConverter::LayoutMinVer < FormatVersion(0, 1, 8), "Time to refactor the code.");
SetVersion(QStringLiteral("0.1.8"));
Save();
}

View File

@ -47,7 +47,7 @@ public:
static const QString LayoutMaxVerStr;
static const QString CurrentSchema;
static Q_DECL_CONSTEXPR const unsigned LayoutMinVer = FormatVersion(0, 1, 0);
static Q_DECL_CONSTEXPR const unsigned LayoutMaxVer = FormatVersion(0, 1, 7);
static Q_DECL_CONSTEXPR const unsigned LayoutMaxVer = FormatVersion(0, 1, 8);
static auto XSDSchemas() -> QHash<unsigned, QString>;
@ -77,6 +77,7 @@ protected:
void ToV0_1_3();
void ToV0_1_5();
void ToV0_1_7();
void ToV0_1_8();
private:
Q_DISABLE_COPY_MOVE(VLayoutConverter) // NOLINT

View File

@ -38,7 +38,6 @@
#include <QLatin1String>
#include <QList>
#include <QUuid>
#include <algorithm>
#include "../exception/vexception.h"
#include "../exception/vexceptionemptyparameter.h"
@ -63,8 +62,8 @@ class QDomElement;
*/
const QString VPatternConverter::PatternMinVerStr = QStringLiteral("0.1.4"); // NOLINT
const QString VPatternConverter::PatternMaxVerStr = QStringLiteral("0.9.3"); // NOLINT
const QString VPatternConverter::CurrentSchema = QStringLiteral("://schema/pattern/v0.9.3.xsd"); // NOLINT
const QString VPatternConverter::PatternMaxVerStr = QStringLiteral("0.9.4"); // NOLINT
const QString VPatternConverter::CurrentSchema = QStringLiteral("://schema/pattern/v0.9.4.xsd"); // NOLINT
// VPatternConverter::PatternMinVer; // <== DON'T FORGET TO UPDATE TOO!!!!
// VPatternConverter::PatternMaxVer; // <== DON'T FORGET TO UPDATE TOO!!!!
@ -265,7 +264,8 @@ auto VPatternConverter::XSDSchemas() -> QHash<unsigned int, QString>
std::make_pair(FormatVersion(0, 9, 0), QStringLiteral("://schema/pattern/v0.9.0.xsd")),
std::make_pair(FormatVersion(0, 9, 1), QStringLiteral("://schema/pattern/v0.9.1.xsd")),
std::make_pair(FormatVersion(0, 9, 2), QStringLiteral("://schema/pattern/v0.9.2.xsd")),
std::make_pair(FormatVersion(0, 9, 3), CurrentSchema)};
std::make_pair(FormatVersion(0, 9, 3), QStringLiteral("://schema/pattern/v0.9.3.xsd")),
std::make_pair(FormatVersion(0, 9, 4), CurrentSchema)};
return schemas;
}
@ -385,10 +385,11 @@ void VPatternConverter::ApplyPatches()
ToV0_9_2();
Q_FALLTHROUGH();
case (FormatVersion(0, 9, 2)):
ToV0_9_3();
case (FormatVersion(0, 9, 3)):
ToV0_9_4();
ValidateXML(CurrentSchema);
Q_FALLTHROUGH();
case (FormatVersion(0, 9, 3)):
case (FormatVersion(0, 9, 4)):
break;
default:
InvalidVersion(m_ver);
@ -406,7 +407,7 @@ void VPatternConverter::DowngradeToCurrentMaxVersion()
auto VPatternConverter::IsReadOnly() const -> bool
{
// Check if attribute readOnly was not changed in file format
Q_STATIC_ASSERT_X(VPatternConverter::PatternMaxVer == FormatVersion(0, 9, 3), "Check attribute readOnly.");
Q_STATIC_ASSERT_X(VPatternConverter::PatternMaxVer == FormatVersion(0, 9, 4), "Check attribute readOnly.");
// Possibly in future attribute readOnly will change position etc.
// For now position is the same for all supported format versions.
@ -582,12 +583,12 @@ void VPatternConverter::ToV0_9_2()
}
//---------------------------------------------------------------------------------------------------------------------
void VPatternConverter::ToV0_9_3()
void VPatternConverter::ToV0_9_4()
{
// TODO. Delete if minimal supported version is 0.9.3
Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < FormatVersion(0, 9, 3), "Time to refactor the code.");
// TODO. Delete if minimal supported version is 0.9.4
Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < FormatVersion(0, 9, 4), "Time to refactor the code.");
SetVersion(QStringLiteral("0.9.3"));
SetVersion(QStringLiteral("0.9.4"));
Save();
}

View File

@ -54,7 +54,7 @@ public:
static const QString PatternMaxVerStr;
static const QString CurrentSchema;
static Q_DECL_CONSTEXPR const unsigned PatternMinVer = FormatVersion(0, 1, 4);
static Q_DECL_CONSTEXPR const unsigned PatternMaxVer = FormatVersion(0, 9, 3);
static Q_DECL_CONSTEXPR const unsigned PatternMaxVer = FormatVersion(0, 9, 4);
static auto XSDSchemas() -> QHash<unsigned, QString>;
@ -91,7 +91,7 @@ private:
void ToV0_9_0();
void ToV0_9_1();
void ToV0_9_2();
void ToV0_9_3();
void ToV0_9_4();
void TagUnitToV0_2_0();
void TagIncrementToV0_2_0();

View File

@ -220,6 +220,25 @@ void dx_iface::InitHeader(VarMeasurement varMeasurement, VarInsunits varInsunits
}
}
auto dx_iface::QtPenStyleToString(Qt::PenStyle style) -> UTF8STRING
{
switch (style)
{
case Qt::DashLine:
return "DASHED";
case Qt::DotLine:
return "DOT";
case Qt::DashDotLine:
return "DASHDOT2";
case Qt::DashDotDotLine:
return "DIVIDE2";
case Qt::NoPen:
case Qt::SolidLine:
default:
return "CONTINUOUS";
}
}
void dx_iface::AddQtLTypes()
{
DRW_LType ltype;

View File

@ -12,50 +12,59 @@
#ifndef DX_IFACE_H
#define DX_IFACE_H
#include "dxfdef.h"
#include "libdxfrw/drw_interface.h"
#include "libdxfrw/libdxfrw.h"
#include "dxfdef.h"
#include <Qt>
class QFont;
// class to store image data and path from DRW_ImageDef
class dx_ifaceImg : public DRW_Image {
class dx_ifaceImg : public DRW_Image
{
public:
dx_ifaceImg()
: path()
{}
{
}
explicit dx_ifaceImg(const DRW_Image &p)
: DRW_Image(p),
path()
{}
{
}
virtual ~dx_ifaceImg() = default;
std::string path; // stores the image path
};
// container class to store entites.
class dx_ifaceBlock final : public DRW_Block {
class dx_ifaceBlock final : public DRW_Block
{
public:
dx_ifaceBlock()
: ent()
{}
{
}
explicit dx_ifaceBlock(const DRW_Block &p)
: DRW_Block(p),
ent()
{}
{
}
virtual ~dx_ifaceBlock(){
virtual ~dx_ifaceBlock()
{
for (std::list<DRW_Entity *>::const_iterator it = ent.begin(); it != ent.end(); ++it)
delete *it;
}
std::list<DRW_Entity *> ent; // stores the entities list
};
// container class to store full dxf data.
class dx_data {
class dx_data
{
public:
dx_data()
: headerC(),
@ -68,9 +77,11 @@ public:
blocks(),
images(),
mBlock(new dx_ifaceBlock())
{}
{
}
~dx_data(){
~dx_data()
{
// cleanup,
for (std::list<dx_ifaceBlock *>::const_iterator it = blocks.begin(); it != blocks.end(); ++it)
delete *it;
@ -88,9 +99,9 @@ public:
std::list<dx_ifaceImg *> images; // temporary list to find images for link with DRW_ImageDef. Do not delete it!!
dx_ifaceBlock *mBlock; // container to store model entities
private:
Q_DISABLE_COPY_MOVE(dx_data) // NOLINT
};
class dx_iface final : public DRW_Interface
@ -125,6 +136,8 @@ public:
auto AddFont(const QFont &f) -> UTF8STRING;
void AddBlock(dx_ifaceBlock *block);
static auto QtPenStyleToString(Qt::PenStyle style) -> UTF8STRING;
void AddQtLTypes();
void AddDefLayers();
void AddAAMALayers();

File diff suppressed because it is too large Load Diff

View File

@ -53,6 +53,7 @@ class DRW_Point;
class DRW_ASTMNotch;
struct VLayoutPassmark;
class DRW_ATTDEF;
class DRW_Circle;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
class VTextCodec;
@ -142,21 +143,30 @@ private:
void ExportAAMAOutline(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportAAMADraw(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportAAMADrawSewLine(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportAAMADrawInternalPaths(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportAAMADrawPlaceLabels(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportAAMAIntcut(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportAAMANotch(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportAAMAGrainline(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportPieceText(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportStyleSystemText(const QSharedPointer<dx_iface> &input, const QVector<VLayoutPiece> &details);
void ExportAAMADrill(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportAAMADrawFoldLine(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
auto ExportToASTM(const QVector<VLayoutPiece> &details) -> bool;
void ExportASTMPieceBoundary(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportASTMSewLine(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportASTMInternalLine(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportASTMDrawInternalPaths(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportASTMDrawPlaceLabels(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportASTMInternalCutout(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportASTMAnnotationText(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportASTMDrill(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportASTMNotches(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportASTMMirrorLine(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportASTMDrawFoldLine(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportAnnotationText(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail,
const UTF8STRING &layer);
Q_REQUIRED_RESULT auto ExportASTMNotch(const VLayoutPassmark &passmark) -> DRW_ASTMNotch *;
Q_REQUIRED_RESULT auto ExportASTMNotchDataDependecy(const VLayoutPassmark &passmark, const UTF8STRING &notchLayer,
@ -170,6 +180,7 @@ private:
Q_REQUIRED_RESULT auto AAMALine(const QLineF &line, const UTF8STRING &layer) -> DRW_Entity *;
Q_REQUIRED_RESULT auto AAMAText(const QPointF &pos, const QString &text, const UTF8STRING &layer) -> DRW_Entity *;
Q_REQUIRED_RESULT auto AAMAPoint(const QPointF &pos, const UTF8STRING &layer) const -> DRW_Point *;
Q_REQUIRED_RESULT auto AAMACircle(const QPointF &pos, const UTF8STRING &layer, qreal radius) const -> DRW_Circle *;
template <class P, class V, class C>
Q_REQUIRED_RESULT auto CreateAAMAPolygon(const QVector<C> &polygon, const UTF8STRING &layer, bool forceClosed)
@ -179,6 +190,16 @@ private:
auto GetFileNameForLocale() const -> std::string;
static auto NotchPrecedingPoint(const QVector<VLayoutPoint> &boundary, QPointF notchBase, QPointF &point) -> bool;
void AAMADrawFoldLineTwoArrows(const QVector<QVector<QPointF>> &points,
const QSharedPointer<dx_ifaceBlock> &detailBlock);
void AAMADrawFoldLineThreeDots(const QVector<QVector<QPointF>> &points,
const QSharedPointer<dx_ifaceBlock> &detailBlock, qreal radius);
void AAMADrawFoldLineThreeX(const QVector<QVector<QPointF>> &points,
const QSharedPointer<dx_ifaceBlock> &detailBlock);
void ASTMDrawFoldLineTwoArrows(const QVector<QVector<QPointF>> &points,
const QSharedPointer<dx_ifaceBlock> &detailBlock);
};
#endif // VDXFENGINE_H

View File

@ -596,7 +596,7 @@ auto VAbstractCurve::DirectionArrows() const -> QVector<DirectionArrow>
}
// Reverse line because we want start arrow from this point
arrow = QLineF(arrow.p2(), arrow.p1());
Swap(arrow);
const qreal angle = arrow.angle(); // we each time change line angle, better save original angle value
arrow.setLength(VAbstractCurve::LengthCurveDirectionArrow());

View File

@ -96,3 +96,18 @@ auto operator>>(QDataStream &dataStream, VLayoutPassmark &data) -> QDataStream &
return dataStream;
}
//---------------------------------------------------------------------------------------------------------------------
auto SingleParallelPoint(const QPointF &p1, const QPointF &p2, qreal angle, qreal width) -> QPointF
{
QLineF pLine(p1, p2);
pLine.setAngle(pLine.angle() + angle);
pLine.setLength(width);
return pLine.p2();
}
//---------------------------------------------------------------------------------------------------------------------
auto SimpleParallelLine(const QPointF &p1, const QPointF &p2, qreal width) -> QLineF
{
return {SingleParallelPoint(p1, p2, 90, width), SingleParallelPoint(p2, p1, -90, width)};
}

View File

@ -88,17 +88,25 @@ Q_DECLARE_METATYPE(VLayoutPassmark) // NOLINT
constexpr qreal accuracyPointOnLine = MmToPixel(0.1555);
Q_REQUIRED_RESULT static inline auto VFuzzyComparePoints(const QPointF &p1, const QPointF &p2,
Q_REQUIRED_RESULT inline auto VFuzzyComparePoints(const QPointF &p1, const QPointF &p2,
qreal accuracy = accuracyPointOnLine) -> bool;
static inline auto VFuzzyComparePoints(const QPointF &p1, const QPointF &p2, qreal accuracy) -> bool
inline auto VFuzzyComparePoints(const QPointF &p1, const QPointF &p2, qreal accuracy) -> bool
{
return QLineF(p1, p2).length() <= accuracy;
}
Q_REQUIRED_RESULT static inline auto VFuzzyOnAxis(qreal v1, qreal v2, qreal accuracy = accuracyPointOnLine) -> bool;
static inline auto VFuzzyOnAxis(qreal v1, qreal v2, qreal accuracy) -> bool
Q_REQUIRED_RESULT inline auto VFuzzyOnAxis(qreal v1, qreal v2, qreal accuracy = accuracyPointOnLine) -> bool;
inline auto VFuzzyOnAxis(qreal v1, qreal v2, qreal accuracy) -> bool
{
return qAbs(v1 - v2) <= accuracy;
}
template <class T> inline void Swap(T &line)
{
line = T(line.p2(), line.p1());
}
auto SingleParallelPoint(const QPointF &p1, const QPointF &p2, qreal angle, qreal width) -> QPointF;
auto SimpleParallelLine(const QPointF &p1, const QPointF &p2, qreal width) -> QLineF;
#endif // VGEOMETRYDEF_H

View File

@ -36,8 +36,8 @@
#include <QVector>
#include <QtGlobal>
#include "vgeometrydef.h"
#include "../vmisc/def.h"
#include "vgeometrydef.h"
class QLineF;
class QPoint;
@ -104,25 +104,24 @@ public:
static auto LineIntersectRect(const QRectF &rec, const QLineF &line) -> QPointF;
static auto IntersectionCircles(const QPointF &c1, double r1, const QPointF &c2, double r2, QPointF &p1,
QPointF &p2) -> int;
static auto LineIntersectCircle(const QPointF &center, qreal radius, const QLineF &line, QPointF &p1,
QPointF &p2) -> qint32;
static auto LineIntersectCircle(const QPointF &center, qreal radius, const QLineF &line, QPointF &p1, QPointF &p2)
-> qint32;
static auto ClosestPoint(const QLineF &line, const QPointF &point) -> QPointF;
static auto addVector(const QPointF &p, const QPointF &p1, const QPointF &p2, qreal k) -> QPointF;
static void LineCoefficients(const QLineF &line, qreal *a, qreal *b, qreal *c);
static auto IsPointOnLineSegment(const QPointF &t, const QPointF &p1, const QPointF &p2,
qreal accuracy = accuracyPointOnLine) -> bool;
static auto IsLineSegmentOnLineSegment (const QLineF &seg1, const QLineF &seg2,
qreal accuracy = accuracyPointOnLine) -> bool;
static auto IsLineSegmentOnLineSegment(const QLineF &seg1, const QLineF &seg2, qreal accuracy = accuracyPointOnLine)
-> bool;
static auto CorrectDistortion(const QPointF &t, const QPointF &p1, const QPointF &p2) -> QPointF;
static auto IsPointOnLineviaPDP(const QPointF &t, const QPointF &p1, const QPointF &p2,
qreal accuracy = accuracyPointOnLine) -> bool;
static auto GetLengthContour(const QVector<QPointF> &contour, const QVector<QPointF> &newPoints) -> int;
template <class T>
static auto PainterPath(const QVector<T> &points) -> QPainterPath;
template <class T> static auto PainterPath(const QVector<T> &points) -> QPainterPath;
protected:
static auto FlippingMatrix(const QLineF &axis) -> QTransform;
private:
QSharedDataPointer<VGObjectData> d;
@ -134,8 +133,7 @@ QT_WARNING_POP
Q_DECLARE_TYPEINFO(VGObject, Q_MOVABLE_TYPE); // NOLINT
//---------------------------------------------------------------------------------------------------------------------
template <class T>
inline auto VGObject::PainterPath(const QVector<T> &points) -> QPainterPath
template <class T> inline auto VGObject::PainterPath(const QVector<T> &points) -> QPainterPath
{
QPainterPath path;
path.setFillRule(Qt::WindingFill);

View File

@ -50,7 +50,8 @@ VLayoutPlaceLabel::VLayoutPlaceLabel(const VPlaceLabelItem &item)
: m_center(item.toQPointF()),
m_type(item.GetLabelType()),
m_rotationMatrix(item.RotationMatrix()),
m_box(item.Box())
m_box(item.Box()),
m_notMirrored(item.IsNotMirrored())
{
}
@ -66,7 +67,8 @@ auto operator<<(QDataStream &dataStream, const VLayoutPlaceLabel &data) -> QData
dataStream << data.m_rotationMatrix;
dataStream << data.m_box;
// Added in classVersion = 2
// Added in classVersion = 3
dataStream << data.m_notMirrored;
return dataStream;
}
@ -110,10 +112,10 @@ auto operator>>(QDataStream &dataStream, VLayoutPlaceLabel &data) -> QDataStream
dataStream >> data.m_rotationMatrix;
dataStream >> data.m_box;
// if (actualClassVersion >= 2)
// {
// }
if (actualClassVersion >= 3)
{
dataStream >> data.m_notMirrored;
}
return dataStream;
}

View File

@ -54,14 +54,18 @@ public:
auto Box() const -> const QRectF &;
void SetBox(const QRectF &newBox);
auto IsNotMirrored() const -> bool;
void SetNotMirrored(bool newNotMirrored);
private:
static constexpr quint32 streamHeader = 0xB282E284; // CRC-32Q string "VLayoutPlaceLabel"
static constexpr quint16 classVersion = 2;
static constexpr quint16 classVersion = 3;
QPointF m_center{};
PlaceLabelType m_type{PlaceLabelType::Button};
QTransform m_rotationMatrix{};
QRectF m_box{};
bool m_notMirrored{false};
};
Q_DECLARE_METATYPE(VLayoutPlaceLabel) // NOLINT
@ -115,4 +119,16 @@ inline void VLayoutPlaceLabel::SetBox(const QRectF &newBox)
m_box = newBox;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto VLayoutPlaceLabel::IsNotMirrored() const -> bool
{
return m_notMirrored;
}
//---------------------------------------------------------------------------------------------------------------------
inline void VLayoutPlaceLabel::SetNotMirrored(bool newNotMirrored)
{
m_notMirrored = newNotMirrored;
}
#endif // VLAYOUTPLACELABEL_H

View File

@ -195,6 +195,18 @@ void VPlaceLabelItem::SetLabelType(PlaceLabelType type)
d->type = type;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPlaceLabelItem::IsNotMirrored() const -> bool
{
return d->notMirrored;
}
//---------------------------------------------------------------------------------------------------------------------
void VPlaceLabelItem::SetNotMirrored(bool value)
{
d->notMirrored = value;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPlaceLabelItem::RotationMatrix() const -> QTransform
{

View File

@ -81,6 +81,9 @@ public:
auto GetLabelType() const -> PlaceLabelType;
void SetLabelType(PlaceLabelType type);
auto IsNotMirrored() const -> bool;
void SetNotMirrored(bool value);
auto RotationMatrix() const -> QTransform;
auto Box() const -> QRectF;

View File

@ -54,6 +54,7 @@ public:
qreal aValue{0}; // NOLINT(misc-non-private-member-variables-in-classes)
qreal correctionAngle{0}; // NOLINT(misc-non-private-member-variables-in-classes)
qreal isVisible{1}; // NOLINT(misc-non-private-member-variables-in-classes)
bool notMirrored{false}; // NOLINT(misc-non-private-member-variables-in-classes)
private:
Q_DISABLE_ASSIGN_MOVE(VPlaceLabelItemData) // NOLINT

View File

@ -30,6 +30,7 @@
#include "../vformat/vsinglelineoutlinechar.h"
#include "../vgeometry/vlayoutplacelabel.h"
#include "../vlayout/vboundary.h"
#include "../vlayout/vfoldline.h"
#include "../vlayout/vlayoutpiece.h"
#include "../vlayout/vlayoutpiecepath.h"
#include "../vlayout/vlayoutpoint.h"
@ -70,6 +71,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(const QString, mPG, ("PG"_L1)) // NOLINT page feed
Q_GLOBAL_STATIC_WITH_ARGS(const QString, mPA, ("PA"_L1)) // NOLINT plot absolute
Q_GLOBAL_STATIC_WITH_ARGS(const QString, mPW, ("PW"_L1)) // NOLINT pen width
Q_GLOBAL_STATIC_WITH_ARGS(const QString, mLA, ("LA"_L1)) // NOLINT line attributes
Q_GLOBAL_STATIC_WITH_ARGS(const QString, mCI, ("CI"_L1)) // NOLINT circle
QT_WARNING_POP
@ -162,12 +164,17 @@ 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, qreal maxLabelHeight) -> QTransform
int maxLineWidth) -> QTransform
{
QTransform labelMatrix;
labelMatrix.translate(topLeft.x(), topLeft.y());
if (piece.IsVerticallyFlipped() || piece.IsHorizontallyFlipped())
if ((piece.IsVerticallyFlipped() && piece.IsHorizontallyFlipped()) ||
(!piece.IsVerticallyFlipped() && !piece.IsHorizontallyFlipped()))
{
labelMatrix.rotate(angle);
}
else if (piece.IsVerticallyFlipped() || piece.IsHorizontallyFlipped())
{
if (piece.IsVerticallyFlipped())
{
@ -178,15 +185,11 @@ auto LineMatrix(const VLayoutPiece &piece, const QPointF &topLeft, qreal angle,
if (piece.IsHorizontallyFlipped())
{
labelMatrix.scale(1, -1);
labelMatrix.scale(-1, 1);
labelMatrix.rotate(-angle);
labelMatrix.translate(0, -maxLabelHeight);
labelMatrix.translate(-maxLineWidth, 0);
}
}
else
{
labelMatrix.rotate(angle);
}
labelMatrix.translate(linePos.x(), linePos.y()); // Each string has own position
labelMatrix *= piece.GetMatrix();
@ -230,72 +233,6 @@ 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
//---------------------------------------------------------------------------------------------------------------------
@ -455,9 +392,11 @@ void VHPGLEngine::ExportDetails(QTextStream &out, const QList<VLayoutPiece> &det
PlotSewLine(out, detail);
PlotInternalPaths(out, detail);
PlotGrainline(out, detail);
PlotMirrorLine(out, detail);
PlotPlaceLabels(out, detail);
PlotPassmarks(out, detail);
PlotLabels(out, detail);
PlotFoldLine(out, detail);
}
}
@ -474,17 +413,21 @@ void VHPGLEngine::PlotSewLine(QTextStream &out, const VLayoutPiece &detail)
{
if (detail.IsSeamAllowance() && not detail.IsHideMainPath() && not detail.IsSeamAllowanceBuiltIn())
{
QVector<VLayoutPoint> sewLine = detail.GetMappedContourPoints();
QVector<VLayoutPoint> const sewLine = detail.GetMappedFullContourPoints();
if (m_togetherWithNotches)
{
const QVector<VLayoutPassmark> passmarks = detail.GetMappedPassmarks();
bool seamAllowance = detail.IsSeamAllowance() && detail.IsSeamAllowanceBuiltIn();
bool builtInSeamAllowance = detail.IsSeamAllowance() && detail.IsSeamAllowanceBuiltIn();
bool const seamAllowance = detail.IsSeamAllowance() && detail.IsSeamAllowanceBuiltIn();
bool const builtInSeamAllowance = detail.IsSeamAllowance() && detail.IsSeamAllowanceBuiltIn();
VBoundary boundary(sewLine, seamAllowance, builtInSeamAllowance);
boundary.SetPieceName(detail.GetName());
if (detail.IsShowFullPiece() && !detail.GetMappedSeamMirrorLine().isNull())
{
boundary.SetMirrorLine(detail.GetMappedSeamMirrorLine());
}
const QList<VBoundarySequenceItemData> sequence = boundary.Combine(passmarks, true, false);
for (const auto &item : sequence)
@ -511,18 +454,22 @@ void VHPGLEngine::PlotSewLine(QTextStream &out, const VLayoutPiece &detail)
void VHPGLEngine::PlotSeamAllowance(QTextStream &out, const VLayoutPiece &detail)
{
QVector<VLayoutPoint> pieceBoundary = detail.IsSeamAllowance() && not detail.IsSeamAllowanceBuiltIn()
? detail.GetMappedSeamAllowancePoints()
: detail.GetMappedContourPoints();
? detail.GetMappedFullSeamAllowancePoints()
: detail.GetMappedFullContourPoints();
if (m_togetherWithNotches)
{
const QVector<VLayoutPassmark> passmarks = detail.GetMappedPassmarks();
bool seamAllowance = detail.IsSeamAllowance() && !detail.IsSeamAllowanceBuiltIn();
bool builtInSeamAllowance = detail.IsSeamAllowance() && detail.IsSeamAllowanceBuiltIn();
bool const seamAllowance = detail.IsSeamAllowance() && !detail.IsSeamAllowanceBuiltIn();
bool const builtInSeamAllowance = detail.IsSeamAllowance() && detail.IsSeamAllowanceBuiltIn();
VBoundary boundary(pieceBoundary, seamAllowance, builtInSeamAllowance);
boundary.SetPieceName(detail.GetName());
if (detail.IsShowFullPiece() && !detail.GetMappedSeamAllowanceMirrorLine().isNull())
{
boundary.SetMirrorLine(detail.GetMappedSeamAllowanceMirrorLine());
}
const QList<VBoundarySequenceItemData> sequence = boundary.Combine(passmarks, false, false);
pieceBoundary.clear();
@ -548,25 +495,50 @@ void VHPGLEngine::PlotSeamAllowance(QTextStream &out, const VLayoutPiece &detail
//---------------------------------------------------------------------------------------------------------------------
void VHPGLEngine::PlotInternalPaths(QTextStream &out, const VLayoutPiece &detail)
{
QVector<VLayoutPiecePath> internalPaths = detail.GetInternalPaths();
QVector<VLayoutPiecePath> const internalPaths = detail.GetInternalPaths();
for (const auto &path : internalPaths)
{
QVector<VLayoutPoint> points = VLayoutPiece::MapVector(
path.Points(), detail.GetMatrix(), detail.IsVerticallyFlipped() || detail.IsHorizontallyFlipped());
PlotPath(out, CastToPoint(ConvertPath(points)), path.PenStyle());
if (!path.IsNotMirrored() && detail.IsShowFullPiece() && !detail.GetMappedSeamMirrorLine().isNull())
{
const QTransform matrix = VGObject::FlippingMatrix(detail.GetMappedSeamMirrorLine());
std::transform(points.begin(), points.end(), points.begin(),
[matrix](const VLayoutPoint &point) { return VAbstractPiece::MapPoint(point, matrix); });
PlotPath(out, CastToPoint(ConvertPath(points)), path.PenStyle());
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VHPGLEngine::PlotPlaceLabels(QTextStream &out, const VLayoutPiece &detail)
{
auto PlotShape = [this, &out](const PlaceLabelImg &shape)
{
for (const auto &subShape : shape)
{
PlotPath(out, CastToPoint(ConvertPath(subShape)), Qt::SolidLine);
}
};
const QVector<VLayoutPlaceLabel> placeLabels = detail.GetPlaceLabels();
for (const auto &pLabel : placeLabels)
{
PlaceLabelImg shape = detail.MapPlaceLabelShape(VAbstractPiece::PlaceLabelShape(pLabel));
for (auto &subShape : shape)
PlotShape(detail.MapPlaceLabelShape(VAbstractPiece::PlaceLabelShape(pLabel)));
if (!pLabel.IsNotMirrored() && detail.IsShowFullPiece() && !detail.GetMappedSeamMirrorLine().isNull())
{
PlotPath(out, CastToPoint(ConvertPath(subShape)), Qt::SolidLine);
PlaceLabelImg shape = detail.MapPlaceLabelShape(VAbstractPiece::PlaceLabelShape(pLabel));
const QTransform matrix = VGObject::FlippingMatrix(detail.GetMappedSeamMirrorLine());
for (auto &points : shape)
{
std::transform(points.begin(), points.end(), points.begin(),
[matrix](const VLayoutPoint &point) { return VAbstractPiece::MapPoint(point, matrix); });
}
PlotShape(shape);
}
}
}
@ -579,14 +551,31 @@ void VHPGLEngine::PlotPassmarks(QTextStream &out, const VLayoutPiece &detail)
return;
}
const QVector<VLayoutPassmark> passmarks = detail.GetMappedPassmarks();
for (const auto &passmark : passmarks)
auto PlotPassmark = [this, &out](const VLayoutPassmark &passmark)
{
for (const auto &subLine : passmark.lines)
{
HPPenUp(out, ConvertPoint(subLine.p1()).toPoint());
HPPenDown(out, ConvertPoint(subLine.p2()).toPoint());
}
};
const QVector<VLayoutPassmark> passmarks = detail.GetMappedPassmarks();
for (const auto &passmark : passmarks)
{
PlotPassmark(passmark);
const QLineF mirrorLine = detail.GetMappedSeamMirrorLine();
if (!mirrorLine.isNull() && detail.IsShowFullPiece())
{
if (!VGObject::IsPointOnLineviaPDP(passmark.baseLine.p1(), mirrorLine.p1(), mirrorLine.p2()))
{
const QTransform matrix = VGObject::FlippingMatrix(mirrorLine);
const VLayoutPassmark mirroredPassmark = VLayoutPiece::MapPassmark(passmark, matrix, false);
PlotPassmark(mirroredPassmark);
}
}
}
}
@ -605,13 +594,128 @@ void VHPGLEngine::PlotGrainline(QTextStream &out, const VLayoutPiece &detail)
return;
}
GrainlineShape shape = detail.GetMappedGrainlineShape();
GrainlineShape const shape = detail.GetMappedGrainlineShape();
for (const auto &subShape : shape)
{
PlotPath(out, CastToPoint(ConvertPath(subShape)), Qt::SolidLine);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VHPGLEngine::PlotMirrorLine(QTextStream &out, const VLayoutPiece &detail)
{
if (detail.IsShowFullPiece())
{
const QLineF mirrorLine = detail.GetMappedSeamAllowanceMirrorLine();
if (not mirrorLine.isNull())
{
PlotPath(out, CastToPoint(ConvertPath<QPointF>({mirrorLine.p1(), mirrorLine.p2()})), Qt::DashDotLine);
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VHPGLEngine::PlotFoldLine(QTextStream &out, const VLayoutPiece &detail)
{
VFoldLine const fLine = detail.FoldLine();
switch (detail.GetFoldLineType())
{
case FoldLineType::TwoArrows:
case FoldLineType::TwoArrowsTextAbove:
case FoldLineType::TwoArrowsTextUnder:
PlotFoldTwoArrowsText(out, fLine);
break;
case FoldLineType::ThreeDots:
PlotFoldThreeDots(out, fLine);
break;
case FoldLineType::ThreeX:
PlotFoldThreeX(out, fLine);
break;
case FoldLineType::LAST_ONE_DO_NOT_USE:
Q_UNREACHABLE();
break;
case FoldLineType::Text:
PlotFoldLineText(out, fLine);
break;
case FoldLineType::None:
default:
break;
};
}
//---------------------------------------------------------------------------------------------------------------------
void VHPGLEngine::PlotFoldLineText(QTextStream &out, const VFoldLine &fLine)
{
QVector<QPainterPath> const path = fLine.FoldLinePath();
if (!path.isEmpty())
{
PlotPainterPath(out, path.constFirst(), Qt::SolidLine);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VHPGLEngine::PlotFoldThreeX(QTextStream &out, const VFoldLine &fLine)
{
QVector<QVector<QPointF>> const points = fLine.FoldLineMarkPoints();
if (points.isEmpty())
{
return;
}
QVector<QPointF> const &shape = points.constFirst();
for (int i = 0; i < shape.size() - 1; i += 2)
{
HPPenUp(out, ConvertPoint(shape.at(i)).toPoint());
HPPenDown(out, ConvertPoint(shape.at(i + 1)).toPoint());
}
}
//---------------------------------------------------------------------------------------------------------------------
void VHPGLEngine::PlotFoldTwoArrowsText(QTextStream &out, const VFoldLine &fLine)
{
QVector<QVector<QPointF>> points = fLine.FoldLineMarkPoints();
if (points.isEmpty() || points.size() != 3)
{
return;
}
points.removeAt(1);
QVector<QPointF> shape;
for (const auto &subShape : points)
{
shape += subShape;
}
const auto arrows = CastToPoint(ConvertPath(shape));
PlotPath(out, arrows, Qt::SolidLine);
QVector<QPainterPath> const path = fLine.FoldLinePath();
if (path.size() > 1)
{
PlotPainterPath(out, path.constLast(), Qt::SolidLine);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VHPGLEngine::PlotFoldThreeDots(QTextStream &out, const VFoldLine &fLine)
{
QVector<QVector<QPointF>> const points = fLine.FoldLineMarkPoints();
if (points.isEmpty() || points.constFirst().size() != 3)
{
return;
}
QVector<QPointF> const &shape = points.constFirst();
qreal const radius = fLine.ThreeDotsRadius();
for (const auto &center : shape)
{
PlotCircle(out, center, radius);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VHPGLEngine::PlotLabel(QTextStream &out, const VLayoutPiece &detail, const QVector<QPointF> &labelShape,
const VTextManager &tm)
@ -639,7 +743,7 @@ void VHPGLEngine::PlotLabelSVGFont(QTextStream &out, const VLayoutPiece &detail,
VSvgFontEngine engine =
db->FontEngine(tm.GetSVGFontFamily(), SVGFontStyle::Normal, SVGFontWeight::Normal, tm.GetSVGFontPointSize());
VSvgFont svgFont = engine.Font();
VSvgFont const svgFont = engine.Font();
if (!svgFont.IsValid())
{
qDebug() << QStringLiteral("Invalid SVG font '%1'. Fallback to outline font.").arg(svgFont.Name());
@ -656,8 +760,6 @@ 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);
@ -671,10 +773,9 @@ 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, labelHeight);
const QTransform lineMatrix = LineMatrix(detail, labelShape.at(0), angle, QPointF(dX, dY), maxLineWidth);
QPainterPath path = lineMatrix.map(engine.DrawPath(QPointF(), qsText));
QPainterPath const path = lineMatrix.map(engine.DrawPath(QPointF(), qsText));
PlotPainterPath(out, path, Qt::SolidLine);
dY += engine.FontHeight() + m_penWidthPx + tm.GetSpacing();
@ -706,20 +807,17 @@ 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());
VSingleLineOutlineChar corrector(fnt);
VSingleLineOutlineChar const corrector(fnt);
if (m_singleStrokeOutlineFont && !corrector.IsPopulated())
{
corrector.LoadCorrections(settings->GetPathFontCorrections());
}
QFontMetrics fm(fnt);
QFontMetrics const fm(fnt);
if (dY + fm.height() > dH)
{
@ -729,8 +827,7 @@ 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, labelHeight);
const QTransform lineMatrix = LineMatrix(detail, labelShape.at(0), angle, QPointF(dX, dY), maxLineWidth);
QPainterPath path;
@ -777,7 +874,7 @@ template <class T> auto VHPGLEngine::ConvertPoint(T point) const -> T
}
//---------------------------------------------------------------------------------------------------------------------
void VHPGLEngine::PlotPath(QTextStream &out, QVector<QPoint> path, Qt::PenStyle penStyle)
void VHPGLEngine::PlotPath(QTextStream &out, const QVector<QPoint> &path, Qt::PenStyle penStyle)
{
if (penStyle == Qt::NoPen)
{
@ -796,22 +893,22 @@ void VHPGLEngine::PlotPath(QTextStream &out, QVector<QPoint> path, Qt::PenStyle
}
else
{
QVector<int> patetrn = PatternForStyle(penStyle);
QVector<int> const patetrn = PatternForStyle(penStyle);
PlotPathForStyle(out, path, patetrn);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VHPGLEngine::PlotSolidLinePath(QTextStream &out, QVector<QPoint> path)
void VHPGLEngine::PlotSolidLinePath(QTextStream &out, const QVector<QPoint> &path)
{
if (path.size() < 2)
{
HPPenUp(out, path.first());
HPPenUp(out, path.constFirst());
HPPenDown(out);
return;
}
HPPenUp(out, path.first());
HPPenUp(out, path.constFirst());
for (int i = 1; i < path.size(); ++i)
{
@ -845,13 +942,13 @@ void VHPGLEngine::PlotPathForStyle(QTextStream &out, QVector<QPoint> path, QVect
for (int i = 1; i < path.size(); ++i)
{
QPointF prevPoint = path.at(i - 1);
QPoint currPoint = path.at(i);
QPoint const currPoint = path.at(i);
qreal distance = QLineF(prevPoint, currPoint).length();
qreal const distance = QLineF(prevPoint, currPoint).length();
qreal segmentDistance = 0;
do
{
qreal subDistance = QLineF(prevPoint, currPoint).length();
qreal const subDistance = QLineF(prevPoint, currPoint).length();
patternDistance = CurrentPatternDistance(patternDistance, dashMode, pattern, patternIndex);
if (subDistance < patternDistance)
@ -913,6 +1010,13 @@ void VHPGLEngine::PlotPainterPath(QTextStream &out, const QPainterPath &path, Qt
}
}
//---------------------------------------------------------------------------------------------------------------------
void VHPGLEngine::PlotCircle(QTextStream &out, const QPointF &center, qreal radius)
{
HPPenUp(out, ConvertPoint(center).toPoint());
HPComand(out, *mCI, QString::number(qFloor(ConvertPixels(radius))));
}
//---------------------------------------------------------------------------------------------------------------------
void VHPGLEngine::HPPenUp(QTextStream &out, QPoint point)
{

View File

@ -47,6 +47,7 @@ class VLayoutPoint;
class QTextStream;
class VTextManager;
class QPainterPath;
class VFoldLine;
class VHPGLEngine
{
@ -121,6 +122,13 @@ private:
void PlotPassmarks(QTextStream &out, const VLayoutPiece &detail);
void PlotLabels(QTextStream &out, const VLayoutPiece &detail);
void PlotGrainline(QTextStream &out, const VLayoutPiece &detail);
void PlotMirrorLine(QTextStream &out, const VLayoutPiece &detail);
void PlotFoldLine(QTextStream &out, const VLayoutPiece &detail);
void PlotFoldLineText(QTextStream &out, const VFoldLine &fLine);
void PlotFoldThreeX(QTextStream &out, const VFoldLine &fLine);
void PlotFoldTwoArrowsText(QTextStream &out, const VFoldLine &fLine);
void PlotFoldThreeDots(QTextStream &out, const VFoldLine &fLine);
void PlotLabel(QTextStream &out, const VLayoutPiece &detail, const QVector<QPointF> &labelShape,
const VTextManager &tm);
@ -131,10 +139,11 @@ private:
template <class T> auto ConvertPath(const QVector<T> &path) const -> QVector<T>;
template <class T> auto ConvertPoint(T point) const -> T;
void PlotPath(QTextStream &out, QVector<QPoint> path, Qt::PenStyle penStyle);
void PlotSolidLinePath(QTextStream &out, QVector<QPoint> path);
void PlotPath(QTextStream &out, const QVector<QPoint> &path, Qt::PenStyle penStyle);
void PlotSolidLinePath(QTextStream &out, const QVector<QPoint> &path);
void PlotPathForStyle(QTextStream &out, QVector<QPoint> path, QVector<int> pattern);
void PlotPainterPath(QTextStream &out, const QPainterPath &path, Qt::PenStyle penStyle);
void PlotCircle(QTextStream &out, const QPointF &center, qreal radius);
void HPPenUp(QTextStream &out, QPoint point);
void HPPenUp(QTextStream &out);

View File

@ -639,22 +639,6 @@ auto AngleBySecondRightAngle(QVector<VRawSAPoint> points, QPointF p1, QPointF p2
return points;
}
//---------------------------------------------------------------------------------------------------------------------
auto SingleParallelPoint(const QPointF &p1, const QPointF &p2, qreal angle, qreal width) -> QPointF
{
QLineF pLine(p1, p2);
pLine.setAngle(pLine.angle() + angle);
pLine.setLength(width);
return pLine.p2();
}
//---------------------------------------------------------------------------------------------------------------------
auto SimpleParallelLine(const QPointF &p1, const QPointF &p2, qreal width) -> QLineF
{
const QLineF paralel = QLineF(SingleParallelPoint(p1, p2, 90, width), SingleParallelPoint(p2, p1, -90, width));
return paralel;
}
//---------------------------------------------------------------------------------------------------------------------
auto BisectorLine(const QPointF &p1, const QPointF &p2, const QPointF &p3) -> QLineF
{
@ -971,7 +955,7 @@ void VAbstractPiece::SetForbidFlipping(bool value)
if (value)
{
SetForceFlipping(not value);
d->m_forceFlipping = not value;
}
}
@ -988,7 +972,7 @@ void VAbstractPiece::SetForceFlipping(bool value)
if (value)
{
SetForbidFlipping(not value);
d->m_forbidFlipping = not value;
}
}
@ -1052,6 +1036,18 @@ void VAbstractPiece::SetSewLineOnDrawing(bool value)
d->m_onDrawing = value;
}
//---------------------------------------------------------------------------------------------------------------------
auto VAbstractPiece::IsShowFullPiece() const -> bool
{
return d->m_showFullPiece;
}
//---------------------------------------------------------------------------------------------------------------------
void VAbstractPiece::SetShowFullPiece(bool value)
{
d->m_showFullPiece = value;
}
//---------------------------------------------------------------------------------------------------------------------
auto VAbstractPiece::GetSAWidth() const -> qreal
{
@ -1521,6 +1517,78 @@ void VAbstractPiece::SetPriority(uint value)
d->m_priority = value;
}
//---------------------------------------------------------------------------------------------------------------------
auto VAbstractPiece::GetFoldLineType() const -> FoldLineType
{
return d->m_foldLineType;
}
//---------------------------------------------------------------------------------------------------------------------
void VAbstractPiece::SetFoldLineType(FoldLineType lineType)
{
d->m_foldLineType = lineType;
}
//---------------------------------------------------------------------------------------------------------------------
auto VAbstractPiece::GetFoldLineSvgFontSize() const -> unsigned int
{
return d->m_foldLineSvgFontSize;
}
//---------------------------------------------------------------------------------------------------------------------
void VAbstractPiece::SetFoldLineSvgFontSize(unsigned int size)
{
d->m_foldLineSvgFontSize = size;
}
//---------------------------------------------------------------------------------------------------------------------
auto VAbstractPiece::IsFoldLineLabelFontItalic() const -> bool
{
return d->m_foldLineLabelFontItalic;
}
//---------------------------------------------------------------------------------------------------------------------
void VAbstractPiece::SetFoldLineLabelFontItalic(bool value)
{
d->m_foldLineLabelFontItalic = value;
}
//---------------------------------------------------------------------------------------------------------------------
auto VAbstractPiece::IsFoldLineLabelFontBold() const -> bool
{
return d->m_foldLineLabelFontBold;
}
//---------------------------------------------------------------------------------------------------------------------
void VAbstractPiece::SetFoldLineLabelFontBold(bool value)
{
d->m_foldLineLabelFontBold = value;
}
//---------------------------------------------------------------------------------------------------------------------
auto VAbstractPiece::GetFoldLineLabel() const -> QString
{
return d->m_foldLineLabel;
}
//---------------------------------------------------------------------------------------------------------------------
void VAbstractPiece::SetFoldLineLabel(const QString &value)
{
d->m_foldLineLabel = value;
}
//---------------------------------------------------------------------------------------------------------------------
auto VAbstractPiece::GetFoldLineLabelAlignment() const -> int
{
return d->m_foldLineLabelAlignment;
}
//---------------------------------------------------------------------------------------------------------------------
void VAbstractPiece::SetFoldLineLabelAlignment(int alignment)
{
d->m_foldLineLabelAlignment = alignment;
}
//---------------------------------------------------------------------------------------------------------------------
auto VAbstractPiece::GetUUID() const -> QUuid
{
@ -1953,6 +2021,7 @@ auto VAbstractPiece::PlaceLabelShape(const VLayoutPlaceLabel &label) -> PlaceLab
}
QVector<VLayoutPoint> shape3;
shape3.reserve(points.size());
for (int i = 0; i < points.size(); ++i)
{
bool turnPoint = false;
@ -1979,6 +2048,7 @@ auto VAbstractPiece::PlaceLabelShape(const VLayoutPlaceLabel &label) -> PlaceLab
}
QVector<VLayoutPoint> circle;
circle.reserve(points.size());
for (int i = 0; i < points.size(); ++i)
{
bool turnPoint = false;

View File

@ -35,9 +35,12 @@
#include <QPointF>
#include <QSharedDataPointer>
#include <QtGlobal>
#include <algorithm>
#include "../vgeometry/vgeometrydef.h"
#include "../vgeometry/vgobject.h"
#include "../vmisc/compatibility.h"
#include "../vmisc/testpath.h"
#include "vrawsapoint.h"
#include "vsapoint.h"
@ -47,6 +50,17 @@ class VGrainlineData;
class VContainer;
class VRawSAPoint;
class VLayoutPlaceLabel;
class VLayoutPoint;
template <typename T> struct IsLayoutPoint
{
static const bool value = false;
};
template <> struct IsLayoutPoint<VLayoutPoint>
{
static const bool value = true;
};
using PlaceLabelImg = QVector<QVector<VLayoutPoint>>;
@ -89,6 +103,9 @@ public:
auto IsSewLineOnDrawing() const -> bool;
void SetSewLineOnDrawing(bool value);
auto IsShowFullPiece() const -> bool;
void SetShowFullPiece(bool value);
auto GetSAWidth() const -> qreal;
void SetSAWidth(qreal value);
@ -101,6 +118,24 @@ public:
auto GetPriority() const -> uint;
void SetPriority(uint value);
auto GetFoldLineType() const -> FoldLineType;
void SetFoldLineType(FoldLineType lineType);
auto GetFoldLineSvgFontSize() const -> unsigned int;
void SetFoldLineSvgFontSize(unsigned int size);
auto IsFoldLineLabelFontItalic() const -> bool;
void SetFoldLineLabelFontItalic(bool value);
auto IsFoldLineLabelFontBold() const -> bool;
void SetFoldLineLabelFontBold(bool value);
auto GetFoldLineLabel() const -> QString;
void SetFoldLineLabel(const QString &value);
auto GetFoldLineLabelAlignment() const -> int;
void SetFoldLineLabelAlignment(int alignment);
auto GetUUID() const -> QUuid;
void SetUUID(const QUuid &uuid);
void SetUUID(const QString &uuid);
@ -142,6 +177,22 @@ public:
template <class T>
static auto RemoveDublicates(const QVector<T> &points, bool removeFirstAndLast = true) -> QVector<T>;
template <class T>
static auto SubdividePath(const QVector<T> &boundary, const QPointF &p, QVector<T> &sub1, QVector<T> &sub2) -> bool;
template <class T> static auto MirrorPath(const QVector<T> &points, const QLineF &mirrorLine) -> QVector<T>;
template <class T> static auto FullPath(const QVector<T> &points, const QLineF &mirrorLine) -> QVector<T>;
template <class T>
static auto MapVector(QVector<T> points, const QTransform &matrix, bool mirror = false) -> QVector<T>;
template <class T>
static auto MapPoint(T obj, const QTransform &matrix) -> typename std::enable_if<!IsLayoutPoint<T>::value, T>::type;
template <class T>
static auto MapPoint(T obj, const QTransform &matrix) -> typename std::enable_if<IsLayoutPoint<T>::value, T>::type;
protected:
static auto IsEkvPointOnLine(const QPointF &iPoint, const QPointF &prevPoint, const QPointF &nextPoint) -> bool;
static auto IsEkvPointOnLine(const VSAPoint &iPoint, const VSAPoint &prevPoint, const VSAPoint &nextPoint) -> bool;
@ -161,6 +212,11 @@ protected:
private:
QSharedDataPointer<VAbstractPieceData> d;
template <typename T>
static auto MakeTurnPoint(const QPointF &p) -> typename std::enable_if<!IsLayoutPoint<T>::value, T>::type;
template <typename T>
static auto MakeTurnPoint(const QPointF &p) -> typename std::enable_if<IsLayoutPoint<T>::value, T>::type;
};
Q_DECLARE_TYPEINFO(VAbstractPiece, Q_MOVABLE_TYPE); // NOLINT
@ -694,4 +750,232 @@ inline auto VAbstractPiece::IntersectionPoint<QPointF>(QPointF crosPoint, const
return crosPoint;
}
//---------------------------------------------------------------------------------------------------------------------
template <typename T>
inline auto VAbstractPiece::MakeTurnPoint(const QPointF &p) ->
typename std::enable_if<!IsLayoutPoint<T>::value, T>::type
{
return p;
}
//---------------------------------------------------------------------------------------------------------------------
template <typename T>
inline auto VAbstractPiece::MakeTurnPoint(const QPointF &p) -> typename std::enable_if<IsLayoutPoint<T>::value, T>::type
{
T breakPoint(p);
breakPoint.SetTurnPoint(true);
return breakPoint;
}
//---------------------------------------------------------------------------------------------------------------------
template <class T>
inline auto VAbstractPiece::SubdividePath(const QVector<T> &boundary, const QPointF &p, QVector<T> &sub1,
QVector<T> &sub2) -> bool
{
if (boundary.size() < 2)
{
return false;
}
bool found = false;
sub1.clear();
sub2.clear();
for (qint32 i = 0; i < boundary.count() - 1; ++i)
{
if (found)
{
if (not VFuzzyComparePoints(boundary.at(i), p))
{
sub2.append(boundary.at(i));
}
if (i + 1 == boundary.count() - 1)
{
sub2.append(boundary.at(i + 1));
}
continue;
}
if (!VGObject::IsPointOnLineSegment(p, static_cast<QPointF>(boundary.at(i)),
static_cast<QPointF>(boundary.at(i + 1))))
{
sub1.append(boundary.at(i));
continue;
}
if (not VFuzzyComparePoints(boundary.at(i), p))
{
sub1.append(boundary.at(i));
}
sub1.append(MakeTurnPoint<T>(p));
sub2.append(MakeTurnPoint<T>(p));
if (i + 1 == boundary.count() - 1 && not VFuzzyComparePoints(boundary.at(i + 1), p))
{
sub2.append(boundary.at(i + 1));
}
found = true;
}
if (not found)
{
sub1.clear();
}
return found;
}
//---------------------------------------------------------------------------------------------------------------------
template <class T>
inline auto VAbstractPiece::MirrorPath(const QVector<T> &points, const QLineF &mirrorLine) -> QVector<T>
{
QVector<T> flipped;
flipped.reserve(points.size());
const QTransform matrix = VGObject::FlippingMatrix(mirrorLine);
for (const auto &p : points)
{
flipped.append(matrix.map(p));
}
return flipped;
}
//---------------------------------------------------------------------------------------------------------------------
template <>
inline auto VAbstractPiece::MirrorPath<VLayoutPoint>(const QVector<VLayoutPoint> &points, const QLineF &mirrorLine)
-> QVector<VLayoutPoint>
{
QVector<VLayoutPoint> flipped;
flipped.reserve(points.size());
const QTransform matrix = VGObject::FlippingMatrix(mirrorLine);
for (const auto &p : points)
{
VLayoutPoint tmp = p;
QPointF const flippedPoint = matrix.map(static_cast<QPointF>(p));
tmp.setX(flippedPoint.x());
tmp.setY(flippedPoint.y());
flipped.append(tmp);
}
return flipped;
}
//---------------------------------------------------------------------------------------------------------------------
template <class T>
inline auto VAbstractPiece::FullPath(const QVector<T> &points, const QLineF &mirrorLine) -> QVector<T>
{
// DumpVector(points, QStringLiteral("input.json.XXXXXX")); // Uncomment for dumping test data
if (mirrorLine.isNull())
{
return points;
}
if (points.size() <= 3)
{
return points;
}
// points = CorrectFullPathInput(points, mirrorLine);
bool closedPath = (points.constFirst() == points.constLast());
bool pathReady = false;
QVector<T> base;
if (VFuzzyComparePoints(points.constFirst(), mirrorLine.p2()))
{
if (closedPath)
{
if (VFuzzyComparePoints(points.at(points.size() - 2), mirrorLine.p1()))
{
base = points;
base.removeLast();
pathReady = true;
}
}
else
{
if (VFuzzyComparePoints(points.constLast(), mirrorLine.p1()))
{
base = points;
pathReady = true;
}
}
}
if (!pathReady)
{
QVector<T> sub1;
QVector<T> sub2;
if (!VAbstractPiece::SubdividePath(points, mirrorLine.p1(), sub1, sub2))
{
return points;
}
QVector<T> reversed = points;
std::reverse(reversed.begin(), reversed.end());
QVector<T> sub3;
QVector<T> sub4;
if (!VAbstractPiece::SubdividePath(reversed, mirrorLine.p2(), sub3, sub4))
{
return points;
}
base = sub3;
std::reverse(base.begin(), base.end());
base += sub1;
pathReady = true;
}
QVector<T> fullPath = MirrorPath(base, mirrorLine);
std::reverse(fullPath.begin(), fullPath.end());
fullPath += base;
// DumpVector(fullPath, QStringLiteral("output.json.XXXXXX")); // Uncomment for dumping test data
return fullPath;
}
//---------------------------------------------------------------------------------------------------------------------
template <class T>
inline auto VAbstractPiece::MapVector(QVector<T> points, const QTransform &matrix, bool mirror) -> QVector<T>
{
std::transform(points.begin(), points.end(), points.begin(),
[matrix](const T &point) { return MapPoint(point, matrix); });
if (mirror)
{
std::reverse(points.begin(), points.end());
}
return points;
}
//---------------------------------------------------------------------------------------------------------------------
template <typename T>
auto VAbstractPiece::MapPoint(T obj, const QTransform &matrix) ->
typename std::enable_if<!IsLayoutPoint<T>::value, T>::type
{
return matrix.map(obj);
}
//---------------------------------------------------------------------------------------------------------------------
template <typename T>
auto VAbstractPiece::MapPoint(T obj, const QTransform &matrix) ->
typename std::enable_if<IsLayoutPoint<T>::value, T>::type
{
auto p = matrix.map(obj);
obj.setX(p.x());
obj.setY(p.y());
return obj;
}
#endif // VABSTRACTPIECE_H

View File

@ -71,12 +71,21 @@ public:
uint m_priority{0}; // NOLINT (misc-non-private-member-variables-in-classes)
QUuid m_uuid{QUuid::createUuid()}; // NOLINT (misc-non-private-member-variables-in-classes)
bool m_onDrawing{false}; // NOLINT (misc-non-private-member-variables-in-classes)
bool m_showFullPiece{true}; // NOLINT (misc-non-private-member-variables-in-classes)
unsigned int m_foldLineSvgFontSize{defFoldLineFontSize}; // NOLINT (misc-non-private-member-variables-in-classes)
bool m_foldLineLabelFontItalic{false}; // NOLINT (misc-non-private-member-variables-in-classes)
bool m_foldLineLabelFontBold{false}; // NOLINT (misc-non-private-member-variables-in-classes)
QString m_foldLineLabel{}; // NOLINT (misc-non-private-member-variables-in-classes)
int m_foldLineLabelAlignment{Qt::AlignHCenter}; // NOLINT (misc-non-private-member-variables-in-classes)
// NOLINTNEXTLINE(misc-non-private-member-variables-in-classes)
FoldLineType m_foldLineType{FoldLineType::TwoArrowsTextAbove};
private:
Q_DISABLE_ASSIGN_MOVE(VAbstractPieceData) // NOLINT
static constexpr quint32 streamHeader = 0x05CDD73A; // CRC-32Q string "VAbstractPieceData"
static constexpr quint16 classVersion = 5;
static constexpr quint16 classVersion = 6;
};
QT_WARNING_POP
@ -116,6 +125,15 @@ inline auto operator<<(QDataStream &dataStream, const VAbstractPieceData &piece)
// Added in classVersion = 5
dataStream << piece.m_followGrainline;
// Added in classVersion = 6
dataStream << piece.m_showFullPiece;
dataStream << piece.m_foldLineSvgFontSize;
dataStream << piece.m_foldLineType;
dataStream << piece.m_foldLineLabelFontItalic;
dataStream << piece.m_foldLineLabelFontBold;
dataStream << piece.m_foldLineLabel;
dataStream << piece.m_foldLineLabelAlignment;
return dataStream;
}
@ -176,6 +194,17 @@ inline auto operator>>(QDataStream &dataStream, VAbstractPieceData &piece) -> QD
dataStream >> piece.m_followGrainline;
}
if (actualClassVersion >= 6)
{
dataStream >> piece.m_showFullPiece;
dataStream >> piece.m_foldLineSvgFontSize;
dataStream >> piece.m_foldLineType;
dataStream >> piece.m_foldLineLabelFontItalic;
dataStream >> piece.m_foldLineLabelFontBold;
dataStream >> piece.m_foldLineLabel;
dataStream >> piece.m_foldLineLabelAlignment;
}
return dataStream;
}

View File

@ -30,10 +30,12 @@
#include "../ifc/exception/vexception.h"
#include "../vgeometry/vgobject.h"
#include "../vmisc/vabstractapplication.h"
#include "vabstractpiece.h"
#include "vlayoutpiecepath.h"
#include <QPoint>
#include <QtDebug>
#include <algorithm>
#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
#include "../vmisc/compatibility.h"
@ -84,211 +86,6 @@ auto PrepareSequenceItem(const QVector<VLayoutPoint> &path, bool drawMode, VBoun
return itemData;
}
//---------------------------------------------------------------------------------------------------------------------
auto PrepareTPassmarkShape(const VLayoutPassmark &passmark, bool drawMode) -> QVector<QVector<VLayoutPoint>>
{
if (passmark.lines.isEmpty())
{
return {};
}
auto TurnPoint = [](QPointF point)
{
VLayoutPoint p(point);
p.SetTurnPoint(true);
return p;
};
QLineF line1 = passmark.lines.constFirst();
QVector<VLayoutPoint> shape1;
shape1.append(TurnPoint(line1.p1()));
shape1.append(TurnPoint(line1.p2()));
if (passmark.lines.size() <= 1)
{
return {shape1};
}
const QLineF &line2 = passmark.lines.constLast();
if (!drawMode)
{
shape1.append(TurnPoint(line2.p1()));
shape1.append(TurnPoint(line2.p2()));
shape1.append(TurnPoint(line1.p2()));
return {shape1};
}
QVector<VLayoutPoint> shape2;
shape2.append(TurnPoint(line2.p1()));
shape2.append(TurnPoint(line2.p2()));
return {shape1, shape2};
}
//---------------------------------------------------------------------------------------------------------------------
auto PrepareExternalVPassmarkShape(const VLayoutPassmark &passmark, bool drawMode) -> QVector<QVector<VLayoutPoint>>
{
if (passmark.lines.isEmpty())
{
return {};
}
auto TurnPoint = [](QPointF point)
{
VLayoutPoint p(point);
p.SetTurnPoint(true);
return p;
};
QLineF line1 = passmark.lines.constFirst();
QVector<VLayoutPoint> shape;
if (!drawMode)
{
shape.append(TurnPoint(line1.p2()));
}
shape.append(TurnPoint(line1.p1()));
shape.append(TurnPoint(line1.p2()));
if (passmark.lines.size() <= 1)
{
return {shape};
}
const QLineF &line2 = passmark.lines.constLast();
shape.append(TurnPoint(line2.p1()));
shape.append(TurnPoint(line2.p2()));
if (!drawMode)
{
shape.append(TurnPoint(line2.p1()));
}
return {shape};
}
//---------------------------------------------------------------------------------------------------------------------
auto PrepareNoneBreakingPassmarkShape(const VLayoutPassmark &passmark) -> QVector<QVector<VLayoutPoint>>
{
auto TurnPoint = [](QPointF point)
{
VLayoutPoint p(point);
p.SetTurnPoint(true);
return p;
};
QVector<VLayoutPoint> shape;
shape.reserve(passmark.lines.size() + 1);
for (int i = 0; i < passmark.lines.size(); ++i)
{
const QLineF &line = passmark.lines.at(i);
shape.append(TurnPoint(line.p1()));
if (passmark.lines.size() - 1 == i)
{
shape.append(TurnPoint(line.p2()));
}
}
return {shape};
}
//---------------------------------------------------------------------------------------------------------------------
auto PrepareUPassmarkShape(const VLayoutPassmark &passmark) -> QVector<QVector<VLayoutPoint>>
{
auto LayoutPoint = [](QPointF point, bool turnPoint, bool curvePoint)
{
VLayoutPoint p(point);
p.SetTurnPoint(turnPoint);
p.SetCurvePoint(curvePoint);
return p;
};
qreal radius = QLineF(passmark.baseLine.p1(), passmark.lines.constFirst().p1()).length();
if (passmark.baseLine.length() - radius > accuracyPointOnLine)
{
QVector<QLineF> lines = passmark.lines;
if (lines.size() < 3)
{
return {};
}
QLineF line1 = lines.takeFirst();
QVector<VLayoutPoint> shape;
shape.reserve(4 + passmark.lines.size() + 1);
shape.append(LayoutPoint(line1.p1(), true, false));
shape.append(LayoutPoint(line1.p2(), true, true));
QLineF line2 = lines.takeLast();
for (int i = 0; i < passmark.lines.size(); ++i)
{
const QLineF &line = passmark.lines.at(i);
shape.append(LayoutPoint(line.p1(), false, true));
if (passmark.lines.size() - 1 == i)
{
shape.append(LayoutPoint(line.p2(), false, true));
}
}
shape.append(LayoutPoint(line2.p1(), true, true));
shape.append(LayoutPoint(line2.p2(), true, false));
return {shape};
}
QVector<VLayoutPoint> shape;
shape.reserve(passmark.lines.size() + 1);
for (int i = 0; i < passmark.lines.size(); ++i)
{
const QLineF &line = passmark.lines.at(i);
shape.append(LayoutPoint(line.p1(), false, true));
if (passmark.lines.size() - 1 == i)
{
shape.append(LayoutPoint(line.p2(), false, true));
}
}
if (!shape.isEmpty())
{
shape.first().SetTurnPoint(true);
shape.last().SetTurnPoint(true);
}
return {shape};
}
//---------------------------------------------------------------------------------------------------------------------
auto PreparePassmarkShape(const VLayoutPassmark &passmark, bool drawMode) -> QVector<QVector<VLayoutPoint>>
{
switch (passmark.type)
{
case PassmarkLineType::OneLine:
case PassmarkLineType::InternalVMark:
case PassmarkLineType::BoxMark:
case PassmarkLineType::CheckMark:
return PrepareNoneBreakingPassmarkShape(passmark);
case PassmarkLineType::ExternalVMark:
return PrepareExternalVPassmarkShape(passmark, drawMode);
case PassmarkLineType::TMark:
return PrepareTPassmarkShape(passmark, drawMode);
case PassmarkLineType::UMark:
return PrepareUPassmarkShape(passmark);
default:
break;
}
return {};
}
//---------------------------------------------------------------------------------------------------------------------
void ConvertTwoLinesPassmark(const VLayoutPassmark &passmark, QList<VBoundarySequenceItemData> &notchSequence)
{
@ -371,170 +168,6 @@ void ConvertThreeLinesPassmark(const VLayoutPassmark &passmark, QList<VBoundaryS
FillSequance(itemData, notchSequence);
}
}
//---------------------------------------------------------------------------------------------------------------------
auto SubdividePath(const QVector<VLayoutPoint> &boundary, const QPointF &p, QVector<VLayoutPoint> &sub1,
QVector<VLayoutPoint> &sub2) -> bool
{
if (boundary.size() < 2)
{
return false;
}
bool found = false;
sub1.clear();
sub2.clear();
auto BreakPoint = [p]()
{
VLayoutPoint breakPoint(p);
breakPoint.SetTurnPoint(true);
return breakPoint;
};
for (qint32 i = 0; i < boundary.count() - 1; ++i)
{
if (found)
{
sub2.append(boundary.at(i));
if (i + 1 == boundary.count() - 1)
{
sub2.append(boundary.at(i + 1));
}
continue;
}
if (!VGObject::IsPointOnLineSegment(p, static_cast<QPointF>(boundary.at(i)),
static_cast<QPointF>(boundary.at(i + 1))))
{
sub1.append(boundary.at(i));
continue;
}
if (not VFuzzyComparePoints(boundary.at(i), p))
{
sub1.append(boundary.at(i));
sub1.append(BreakPoint());
}
else
{
if (not sub1.isEmpty())
{
sub1.append(BreakPoint());
}
}
if (not VFuzzyComparePoints(boundary.at(i + 1), p))
{
sub2.append(BreakPoint());
if (i + 1 == boundary.count() - 1)
{
sub2.append(boundary.at(i + 1));
}
}
found = true;
}
if (not found)
{
sub1.clear();
}
return found;
}
//---------------------------------------------------------------------------------------------------------------------
auto InsertDisconnect(QList<VBoundarySequenceItemData> &sequence, int i, const VBoundarySequenceItemData &item,
bool drawMode) -> bool
{
auto passmark = item.item.value<VLayoutPassmark>();
bool inserted = false;
const auto boundary = sequence.at(i).item.value<VLayoutPiecePath>().Points();
QVector<VLayoutPoint> sub1;
QVector<VLayoutPoint> sub2;
if (!SubdividePath(boundary, passmark.baseLine.p1(), sub1, sub2))
{
return false;
}
sequence.removeAt(i);
if (not sub2.isEmpty())
{
sequence.insert(i, PrepareSequenceItem(sub2, drawMode, VBoundarySequenceItem::Boundary));
}
QVector<QVector<VLayoutPoint>> shape = PreparePassmarkShape(passmark, drawMode);
for (auto &subShape : shape)
{
sequence.insert(i, PrepareSequenceItem(subShape, drawMode, VBoundarySequenceItem::PassmarkShape));
}
if (not sub1.isEmpty())
{
sequence.insert(i, PrepareSequenceItem(sub1, drawMode, VBoundarySequenceItem::Boundary));
}
inserted = true;
return inserted;
}
//---------------------------------------------------------------------------------------------------------------------
auto InsertCutOut(QList<VBoundarySequenceItemData> &sequence, int i, const VBoundarySequenceItemData &item,
bool drawMode) -> bool
{
auto passmark = item.item.value<VLayoutPassmark>();
QVector<QVector<VLayoutPoint>> shape = PreparePassmarkShape(passmark, drawMode);
if (shape.isEmpty())
{
return false;
}
const QVector<VLayoutPoint> &subShape = shape.constFirst();
if (subShape.size() < 2)
{
return false;
}
const auto boundary = sequence.at(i).item.value<VLayoutPiecePath>().Points();
QVector<VLayoutPoint> startSub1;
QVector<VLayoutPoint> startSub2;
if (!SubdividePath(boundary, subShape.constFirst(), startSub1, startSub2))
{
return false;
}
QVector<VLayoutPoint> endSub1;
QVector<VLayoutPoint> endSub2;
if (!SubdividePath(boundary, subShape.constLast(), endSub1, endSub2))
{
return false;
}
sequence.removeAt(i);
if (not endSub2.isEmpty())
{
sequence.insert(i, PrepareSequenceItem(endSub2, drawMode, VBoundarySequenceItem::Boundary));
}
sequence.insert(i, PrepareSequenceItem(subShape, drawMode, VBoundarySequenceItem::PassmarkShape));
if (not startSub1.isEmpty())
{
sequence.insert(i, PrepareSequenceItem(startSub1, drawMode, VBoundarySequenceItem::Boundary));
}
return true;
}
} // namespace
//---------------------------------------------------------------------------------------------------------------------
@ -585,6 +218,16 @@ auto VBoundary::Combine(const QVector<VLayoutPassmark> &passmarks, bool drawMode
if (item.type == VBoundarySequenceItem::Passmark)
{
InsertPassmark(item, sequence, drawMode);
if (!m_mirrorLine.isNull())
{
auto passmark = item.item.value<VLayoutPassmark>();
if (!VGObject::IsPointOnLineviaPDP(passmark.baseLine.p1(), m_mirrorLine.p1(), m_mirrorLine.p2()))
{
item.mirror = true;
InsertPassmark(item, sequence, drawMode);
}
}
}
}
@ -680,3 +323,369 @@ void VBoundary::InsertPassmark(const VBoundarySequenceItemData &item, QList<VBou
: qWarning() << VAbstractApplication::warningMessageSignature + errorMsg;
}
}
//---------------------------------------------------------------------------------------------------------------------
auto VBoundary::InsertDisconnect(QList<VBoundarySequenceItemData> &sequence, int i,
const VBoundarySequenceItemData &item, bool drawMode) const -> bool
{
auto passmark = item.item.value<VLayoutPassmark>();
bool inserted = false;
const auto boundary = sequence.at(i).item.value<VLayoutPiecePath>().Points();
QPointF connectionPoint = passmark.baseLine.p1();
if (item.mirror && !m_mirrorLine.isNull())
{
const QTransform matrix = VGObject::FlippingMatrix(m_mirrorLine);
connectionPoint = matrix.map(connectionPoint);
}
QVector<VLayoutPoint> sub1;
QVector<VLayoutPoint> sub2;
if (!VAbstractPiece::SubdividePath(boundary, connectionPoint, sub1, sub2))
{
return false;
}
sequence.removeAt(i);
if (not sub2.isEmpty())
{
sequence.insert(i, PrepareSequenceItem(sub2, drawMode, VBoundarySequenceItem::Boundary));
}
QVector<QVector<VLayoutPoint>> shape = PreparePassmarkShape(passmark, drawMode, item.mirror);
for (auto &subShape : shape)
{
sequence.insert(i, PrepareSequenceItem(subShape, drawMode, VBoundarySequenceItem::PassmarkShape));
}
if (not sub1.isEmpty())
{
sequence.insert(i, PrepareSequenceItem(sub1, drawMode, VBoundarySequenceItem::Boundary));
}
inserted = true;
return inserted;
}
//---------------------------------------------------------------------------------------------------------------------
auto VBoundary::InsertCutOut(QList<VBoundarySequenceItemData> &sequence, int i, const VBoundarySequenceItemData &item,
bool drawMode) const -> bool
{
auto passmark = item.item.value<VLayoutPassmark>();
QVector<QVector<VLayoutPoint>> shape = PreparePassmarkShape(passmark, drawMode, item.mirror);
if (shape.isEmpty())
{
return false;
}
const QVector<VLayoutPoint> &subShape = shape.constFirst();
if (subShape.size() < 2)
{
return false;
}
const auto boundary = sequence.at(i).item.value<VLayoutPiecePath>().Points();
QVector<VLayoutPoint> startSub1;
QVector<VLayoutPoint> startSub2;
if (!VAbstractPiece::SubdividePath(boundary, subShape.constFirst(), startSub1, startSub2))
{
return false;
}
QVector<VLayoutPoint> endSub1;
QVector<VLayoutPoint> endSub2;
if (!VAbstractPiece::SubdividePath(boundary, subShape.constLast(), endSub1, endSub2))
{
return false;
}
sequence.removeAt(i);
if (not endSub2.isEmpty())
{
sequence.insert(i, PrepareSequenceItem(endSub2, drawMode, VBoundarySequenceItem::Boundary));
}
sequence.insert(i, PrepareSequenceItem(subShape, drawMode, VBoundarySequenceItem::PassmarkShape));
if (not startSub1.isEmpty())
{
sequence.insert(i, PrepareSequenceItem(startSub1, drawMode, VBoundarySequenceItem::Boundary));
}
return true;
}
//---------------------------------------------------------------------------------------------------------------------
auto VBoundary::PreparePassmarkShape(const VLayoutPassmark &passmark, bool drawMode, bool mirrorNotch) const
-> QVector<QVector<VLayoutPoint>>
{
switch (passmark.type)
{
case PassmarkLineType::OneLine:
case PassmarkLineType::InternalVMark:
case PassmarkLineType::BoxMark:
case PassmarkLineType::CheckMark:
return PrepareNoneBreakingPassmarkShape(passmark, mirrorNotch);
case PassmarkLineType::ExternalVMark:
return PrepareExternalVPassmarkShape(passmark, drawMode, mirrorNotch);
case PassmarkLineType::TMark:
return PrepareTPassmarkShape(passmark, drawMode, mirrorNotch);
case PassmarkLineType::UMark:
return PrepareUPassmarkShape(passmark, mirrorNotch);
default:
break;
}
return {};
}
//---------------------------------------------------------------------------------------------------------------------
auto VBoundary::PrepareNoneBreakingPassmarkShape(const VLayoutPassmark &passmark, bool mirrorNotch) const
-> QVector<QVector<VLayoutPoint>>
{
auto TurnPoint = [](QPointF point)
{
VLayoutPoint p(point);
p.SetTurnPoint(true);
return p;
};
QVector<QLineF> lines = passmark.lines;
if (mirrorNotch && !m_mirrorLine.isNull())
{
const QTransform matrix = VGObject::FlippingMatrix(m_mirrorLine);
lines = VAbstractPiece::MapVector(lines, matrix);
}
QVector<VLayoutPoint> shape;
shape.reserve(lines.size() + 1);
for (int i = 0; i < lines.size(); ++i)
{
const QLineF &line = lines.at(i);
shape.append(TurnPoint(line.p1()));
if (lines.size() - 1 == i)
{
shape.append(TurnPoint(line.p2()));
}
}
if (mirrorNotch && !m_mirrorLine.isNull() &&
(passmark.type == PassmarkLineType::InternalVMark || passmark.type == PassmarkLineType::BoxMark ||
passmark.type == PassmarkLineType::CheckMark))
{
std::reverse(shape.begin(), shape.end());
}
return {shape};
}
//---------------------------------------------------------------------------------------------------------------------
auto VBoundary::PrepareExternalVPassmarkShape(const VLayoutPassmark &passmark, bool drawMode, bool mirrorNotch) const
-> QVector<QVector<VLayoutPoint>>
{
if (passmark.lines.isEmpty())
{
return {};
}
auto TurnPoint = [](QPointF point)
{
VLayoutPoint p(point);
p.SetTurnPoint(true);
return p;
};
QVector<QLineF> lines = passmark.lines;
if (mirrorNotch && !m_mirrorLine.isNull())
{
const QTransform matrix = VGObject::FlippingMatrix(m_mirrorLine);
lines = VAbstractPiece::MapVector(lines, matrix);
}
QLineF line1 = lines.constFirst();
QVector<VLayoutPoint> shape;
if (!drawMode)
{
shape.append(TurnPoint(line1.p2()));
}
shape.append(TurnPoint(line1.p1()));
shape.append(TurnPoint(line1.p2()));
if (lines.size() <= 1)
{
return {shape};
}
const QLineF &line2 = lines.constLast();
shape.append(TurnPoint(line2.p1()));
shape.append(TurnPoint(line2.p2()));
if (!drawMode)
{
shape.append(TurnPoint(line2.p1()));
if (mirrorNotch && !m_mirrorLine.isNull())
{
std::reverse(shape.begin(), shape.end());
}
}
return {shape};
}
//---------------------------------------------------------------------------------------------------------------------
auto VBoundary::PrepareTPassmarkShape(const VLayoutPassmark &passmark, bool drawMode, bool mirrorNotch) const
-> QVector<QVector<VLayoutPoint>>
{
if (passmark.lines.isEmpty())
{
return {};
}
auto TurnPoint = [](QPointF point)
{
VLayoutPoint p(point);
p.SetTurnPoint(true);
return p;
};
QVector<QLineF> lines = passmark.lines;
if (mirrorNotch && !m_mirrorLine.isNull())
{
const QTransform matrix = VGObject::FlippingMatrix(m_mirrorLine);
lines = VAbstractPiece::MapVector(lines, matrix);
}
QLineF line1 = lines.constFirst();
QVector<VLayoutPoint> shape1;
shape1.append(TurnPoint(line1.p1()));
shape1.append(TurnPoint(line1.p2()));
if (lines.size() <= 1)
{
return {shape1};
}
const QLineF &line2 = lines.constLast();
if (!drawMode)
{
shape1.append(TurnPoint(line2.p1()));
shape1.append(TurnPoint(line2.p2()));
shape1.append(TurnPoint(line1.p2()));
if (mirrorNotch && !m_mirrorLine.isNull())
{
std::reverse(shape1.begin(), shape1.end());
}
return {shape1};
}
QVector<VLayoutPoint> shape2;
shape2.append(TurnPoint(line2.p1()));
shape2.append(TurnPoint(line2.p2()));
return {shape1, shape2};
}
//---------------------------------------------------------------------------------------------------------------------
auto VBoundary::PrepareUPassmarkShape(const VLayoutPassmark &passmark, bool mirrorNotch) const
-> QVector<QVector<VLayoutPoint>>
{
auto LayoutPoint = [](QPointF point, bool turnPoint, bool curvePoint)
{
VLayoutPoint p(point);
p.SetTurnPoint(turnPoint);
p.SetCurvePoint(curvePoint);
return p;
};
if (passmark.lines.isEmpty())
{
return {};
}
qreal radius = QLineF(passmark.baseLine.p1(), passmark.lines.constFirst().p1()).length();
QVector<QLineF> lines = passmark.lines;
if (mirrorNotch && !m_mirrorLine.isNull())
{
const QTransform matrix = VGObject::FlippingMatrix(m_mirrorLine);
lines = VAbstractPiece::MapVector(lines, matrix);
}
if (passmark.baseLine.length() - radius > accuracyPointOnLine)
{
if (lines.size() < 3)
{
return {};
}
QLineF line1 = lines.takeFirst();
QVector<VLayoutPoint> shape;
shape.reserve(4 + passmark.lines.size() + 1);
shape.append(LayoutPoint(line1.p1(), true, false));
shape.append(LayoutPoint(line1.p2(), true, true));
QLineF line2 = lines.takeLast();
for (int i = 0; i < lines.size(); ++i)
{
const QLineF &line = lines.at(i);
shape.append(LayoutPoint(line.p1(), false, true));
if (lines.size() - 1 == i)
{
shape.append(LayoutPoint(line.p2(), false, true));
}
}
shape.append(LayoutPoint(line2.p1(), true, true));
shape.append(LayoutPoint(line2.p2(), true, false));
if (mirrorNotch && !m_mirrorLine.isNull())
{
std::reverse(shape.begin(), shape.end());
}
return {shape};
}
QVector<VLayoutPoint> shape;
shape.reserve(lines.size() + 1);
for (int i = 0; i < lines.size(); ++i)
{
const QLineF &line = lines.at(i);
shape.append(LayoutPoint(line.p1(), false, true));
if (lines.size() - 1 == i)
{
shape.append(LayoutPoint(line.p2(), false, true));
}
}
if (!shape.isEmpty())
{
shape.first().SetTurnPoint(true);
shape.last().SetTurnPoint(true);
}
if (mirrorNotch && !m_mirrorLine.isNull())
{
std::reverse(shape.begin(), shape.end());
}
return {shape};
}

View File

@ -50,6 +50,7 @@ struct VBoundarySequenceItemData
int number{0};
VBoundarySequenceItem type{VBoundarySequenceItem::Unknown};
QVariant item{};
bool mirror{false};
};
class VBoundary
@ -63,17 +64,35 @@ public:
-> QList<VBoundarySequenceItemData>;
void SetPieceName(const QString &newPieceName);
void SetMirrorLine(const QLineF &newMirrorLine);
private:
QVector<VLayoutPoint> m_boundary;
bool m_seamAllowance;
bool m_builtInSeamAllowance;
QString m_pieceName{};
QLineF m_mirrorLine{};
auto SkipPassmark(const VLayoutPassmark &passmark, bool layoutAllowance) const -> bool;
void InsertPassmark(const VBoundarySequenceItemData &item, QList<VBoundarySequenceItemData> &sequence,
bool drawMode) const;
auto InsertDisconnect(QList<VBoundarySequenceItemData> &sequence, int i, const VBoundarySequenceItemData &item,
bool drawMode) const -> bool;
auto InsertCutOut(QList<VBoundarySequenceItemData> &sequence, int i, const VBoundarySequenceItemData &item,
bool drawMode) const -> bool;
auto PreparePassmarkShape(const VLayoutPassmark &passmark, bool drawMode, bool mirrorNotch) const
-> QVector<QVector<VLayoutPoint>>;
auto PrepareNoneBreakingPassmarkShape(const VLayoutPassmark &passmark, bool mirrorNotch) const
-> QVector<QVector<VLayoutPoint>>;
auto PrepareExternalVPassmarkShape(const VLayoutPassmark &passmark, bool drawMode, bool mirrorNotch) const
-> QVector<QVector<VLayoutPoint>>;
auto PrepareTPassmarkShape(const VLayoutPassmark &passmark, bool drawMode, bool mirrorNotch) const
-> QVector<QVector<VLayoutPoint>>;
auto PrepareUPassmarkShape(const VLayoutPassmark &passmark, bool mirrorNotch) const
-> QVector<QVector<VLayoutPoint>>;
};
//---------------------------------------------------------------------------------------------------------------------
@ -82,4 +101,10 @@ inline void VBoundary::SetPieceName(const QString &newPieceName)
m_pieceName = newPieceName;
}
//---------------------------------------------------------------------------------------------------------------------
inline void VBoundary::SetMirrorLine(const QLineF &newMirrorLine)
{
m_mirrorLine = newMirrorLine;
}
#endif // VBOUNDARY_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,156 @@
/************************************************************************
**
** @file vfoldline.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 20 12, 2023
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2023 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VFOLDLINE_H
#define VFOLDLINE_H
#include <QCoreApplication>
#include <QFont>
#include <QLineF>
#include <QTransform>
#include "../vmisc/def.h"
class QPainterPath;
class VSvgFontEngine;
class QGraphicsSimpleTextItem;
struct TextPosData
{
qreal labelWidth{0};
qreal labelHeight{0};
QLineF base{};
};
struct ArrowsTextPosData : public TextPosData
{
qreal arrowsWidth{0};
qreal arrowsHeight{0};
};
struct ThreeDotsPosData
{
qreal width{0};
qreal defHeight{0};
qreal height{0};
qreal radius{0};
qreal margin{0};
};
struct FoldLabelPosData
{
QFont font{};
QPointF pos{};
QString label{};
qreal angle{0};
};
class VFoldLine
{
Q_DECLARE_TR_FUNCTIONS(VFoldLine) // NOLINT
public:
VFoldLine(const QLineF &line, FoldLineType type);
void SetHeight(qreal newHeight);
void SetWidth(qreal newWidth);
void SetCenterPosition(qreal newCenter);
void SetLabel(const QString &newLabel);
void SetLabelSvgFontSize(unsigned int newFontSize);
void SetLabelFontItalic(bool newItalic);
void SetLabelFontBold(bool newBold);
void SetLabelAlignment(int alignment);
void SetMatrix(const QTransform &matrix);
void SetVerticallyFlipped(bool value);
void SetHorizontallyFlipped(bool value);
void SetXScale(qreal xs);
void SetYScale(qreal ys);
void SetOutlineFont(const QFont &font);
void SetSvgFont(const QString &font);
auto FoldLinePath() const -> QVector<QPainterPath>;
auto FoldLineMarkPoints() const -> QVector<QVector<QPointF>>;
auto LabelPosition(bool &ok) const -> FoldLabelPosData;
void UpdateFoldLineLabel(QGraphicsSimpleTextItem *item) const;
auto ThreeDotsRadius() const -> qreal;
static auto DefaultFoldLineLabel() -> QString;
private:
QLineF m_foldLine{};
FoldLineType m_type{FoldLineType::TwoArrowsTextAbove};
qreal m_height{0};
qreal m_width{0};
qreal m_center{0.5};
QString m_label{};
unsigned int m_svgFontSize{defFoldLineFontSize};
bool m_italic{false};
bool m_bold{false};
int m_alignment{Qt::AlignHCenter};
QTransform m_matrix{};
bool m_verticallyFlipped{false};
bool m_horizontallyFlipped{false};
qreal m_xScale{1.0};
qreal m_yScale{1.0};
QFont m_outlineFont{};
QString m_svgFont{};
auto FoldLineTwoArrowsPath() const -> QVector<QPainterPath>;
auto FoldLineTwoArrowsTextAbovePath() const -> QVector<QPainterPath>;
auto FoldLineTwoArrowsTextUnderPath() const -> QVector<QPainterPath>;
auto FoldLineTextPath() const -> QVector<QPainterPath>;
auto FoldLineThreeDotsPath() const -> QVector<QPainterPath>;
auto FoldLineThreeXPath() const -> QVector<QPainterPath>;
auto TrueCenter(const QLineF &base, qreal width) const -> QPointF;
auto FoldLineLabel() const -> QString;
auto OutlineFontLabel(const QLineF &base, qreal width, qreal textHeight) const -> QPainterPath;
auto SVGFontLabel(const QLineF &base, qreal width, qreal textHeight) const -> QPainterPath;
auto LabelTextHeight() const -> qreal;
auto LabelSVGFontEngine(VSvgFontEngine &engine) const -> bool;
auto LabelOutlineFont() const -> QFont;
auto TwoArrowsPath(qreal width, qreal height) const -> QPainterPath;
auto TwoArrowsPoints(qreal width, qreal height) const -> QVector<QVector<QPointF>>;
auto ThreeDotsPoints() const -> QVector<QVector<QPointF>>;
auto ThreeXPoints() const -> QVector<QVector<QPointF>>;
auto TwoArrowsData() const -> ArrowsTextPosData;
auto TwoArrowsTextAboveData() const -> ArrowsTextPosData;
auto TwoArrowsTextUnderData() const -> ArrowsTextPosData;
auto TextData() const -> TextPosData;
auto ThreeDotsData() const -> ThreeDotsPosData;
};
#endif // VFOLDLINE_H

View File

@ -66,3 +66,15 @@ void VGraphicsFillItem::paint(QPainter *painter, const QStyleOptionGraphicsItem
painter->drawPath(path());
painter->restore();
}
//---------------------------------------------------------------------------------------------------------------------
VGraphicsFoldLineItem::VGraphicsFoldLineItem(QGraphicsItem *parent)
: VGraphicsFillItem(parent)
{
}
//---------------------------------------------------------------------------------------------------------------------
VGraphicsFoldLineItem::VGraphicsFoldLineItem(const QPainterPath &path, QGraphicsItem *parent)
: VGraphicsFillItem(path, parent)
{
}

View File

@ -97,4 +97,22 @@ inline void VGraphicsFillItem::SetCustomPen(bool newCustomPen)
{
m_customPen = newCustomPen;
}
class VGraphicsFoldLineItem : public VGraphicsFillItem
{
public:
explicit VGraphicsFoldLineItem(QGraphicsItem *parent = nullptr);
explicit VGraphicsFoldLineItem(const QPainterPath &path, QGraphicsItem *parent = nullptr);
~VGraphicsFoldLineItem() override = default;
auto type() const -> int override { return Type; }
enum
{
Type = UserType + static_cast<int>(Layout::FoldLineItem)
};
private:
Q_DISABLE_COPY_MOVE(VGraphicsFoldLineItem) // NOLINT
};
#endif // VGRAPHICSFILLITEM_H

View File

@ -31,7 +31,8 @@ HEADERS += \
$$PWD/vlayoutpiecepath_p.h \
$$PWD/vbestsquare_p.h \
$$PWD/vrawsapoint.h \
$$PWD/vboundary.h
$$PWD/vboundary.h \
$$PWD/vfoldline.h
SOURCES += \
$$PWD/vlayoutexporter.cpp \
@ -52,6 +53,7 @@ SOURCES += \
$$PWD/vlayoutpiece.cpp \
$$PWD/vlayoutpiecepath.cpp \
$$PWD/vrawsapoint.cpp \
$$PWD/vboundary.cpp
$$PWD/vboundary.cpp \
$$PWD/vfoldline.cpp
*msvc*:SOURCES += $$PWD/stable.cpp

View File

@ -57,7 +57,9 @@ VLib {
"vlayoutpiecepath.cpp",
"vrawsapoint.cpp",
"vboundary.h",
"vboundary.cpp"
"vboundary.cpp",
"vfoldline.h",
"vfoldline.cpp"
];
if (Qt.core.versionMajor >= 5 && Qt.core.versionMinor < 12) {

View File

@ -52,11 +52,12 @@
#include "../vgeometry/vlayoutplacelabel.h"
#include "../vgeometry/vplacelabelitem.h"
#include "../vgeometry/vpointf.h"
#include "../vlayout/vabstractpiece.h"
#include "../vmisc/compatibility.h"
#include "../vmisc/def.h"
#include "../vmisc/literals.h"
#include "../vmisc/svgfont/vsvgfontdatabase.h"
#include "../vmisc/svgfont/vsvgfontengine.h"
#include "../vmisc/testpath.h"
#include "../vmisc/vabstractvalapplication.h"
#include "../vpatterndb/calculator.h"
#include "../vpatterndb/floatItemData/vgrainlinedata.h"
@ -64,10 +65,14 @@
#include "../vpatterndb/floatItemData/vpiecelabeldata.h"
#include "../vpatterndb/variables/vmeasurement.h"
#include "../vpatterndb/vcontainer.h"
#include "../vpatterndb/vformula.h"
#include "../vpatterndb/vpassmark.h"
#include "../vpatterndb/vpiecenode.h"
#include "../vwidgets/vpiecegrainline.h"
#include "vabstractpiece.h"
#include "vboundary.h"
#include "vcommonsettings.h"
#include "vfoldline.h"
#include "vgraphicsfillitem.h"
#include "vlayoutpiece_p.h"
#include "vtextmanager.h"
@ -95,6 +100,7 @@ auto ConvertInternalPaths(const VPiece &piece, const VContainer *pattern) -> QVe
VLayoutPiecePath convertedPath(path.PathPoints(pattern, cuttingPath));
convertedPath.SetCutPath(path.IsCutPath());
convertedPath.SetPenStyle(path.GetPenType());
convertedPath.SetNotMirrored(path.IsNotMirrored());
paths.append(convertedPath);
}
}
@ -468,6 +474,70 @@ auto PrepareGradationId(const QString &label, const VContainer *pattern) -> QStr
const QMap<QString, QString> placeholders = PrepareGradationPlaceholders(pattern);
return ReplacePlaceholders(placeholders, label);
}
//---------------------------------------------------------------------------------------------------------------------
void InitFoldLine(VLayoutPiece &det, const VPiece &piece, const VContainer *pattern)
{
det.SetFoldLineType(piece.GetFoldLineType());
if (piece.GetFoldLineType() == FoldLineType::None)
{
return;
}
det.SetFoldLineSvgFontSize(piece.GetFoldLineSvgFontSize());
det.SetFoldLineLabelFontItalic(piece.IsFoldLineLabelFontItalic());
det.SetFoldLineLabelFontBold(piece.IsFoldLineLabelFontBold());
det.SetFoldLineLabel(piece.GetFoldLineLabel());
det.SetFoldLineLabelAlignment(piece.GetFoldLineLabelAlignment());
{
VCommonSettings *settings = VAbstractApplication::VApp()->Settings();
QFont font = settings->GetLabelFont();
font.setPointSize(static_cast<int>(piece.GetFoldLineSvgFontSize()));
det.SetFoldLineOutlineFont(font);
det.SetFoldLineSVGFontFamily(settings->GetLabelSVGFont());
}
if (piece.IsManualFoldHeight())
{
VFormula formula(piece.GetFormulaFoldHeight(), pattern);
formula.setCheckZero(false);
formula.setCheckLessThanZero(true);
formula.Eval();
if (!formula.error())
{
det.SetFoldLineHeight(ToPixel(formula.getDoubleValue(), *pattern->GetPatternUnit()));
}
}
if (piece.IsManualFoldWidth())
{
VFormula formula(piece.GetFormulaFoldWidth(), pattern);
formula.setCheckZero(false);
formula.setCheckLessThanZero(true);
formula.Eval();
if (!formula.error())
{
det.SetFoldLineWidth(ToPixel(formula.getDoubleValue(), *pattern->GetPatternUnit()));
}
}
if (piece.IsManualFoldCenter())
{
VFormula formula(piece.GetFormulaFoldCenter(), pattern);
formula.setCheckZero(false);
formula.setCheckLessThanZero(true);
formula.Eval();
if (!formula.error())
{
det.SetFoldLineCenterPosition(formula.getDoubleValue());
}
}
}
} // namespace
// Friend functions
@ -557,16 +627,26 @@ VLayoutPiece::~VLayoutPiece() = default;
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::Create(const VPiece &piece, vidtype id, const VContainer *pattern) -> VLayoutPiece
{
QFuture<QVector<VLayoutPoint>> futureSeamAllowance =
QtConcurrent::run([piece, pattern]() { return piece.SeamAllowancePoints(pattern); });
QFuture<bool> futureSeamAllowanceValid =
QFuture<QVector<VLayoutPoint>> const futureSeamAllowance = QtConcurrent::run(
[piece, pattern]()
{
if (!piece.SeamMirrorLine(pattern).isNull())
{
VPiece tmp = piece;
tmp.SetShowFullPiece(false);
return tmp.SeamAllowancePoints(pattern);
}
return piece.SeamAllowancePoints(pattern);
});
QFuture<bool> const futureSeamAllowanceValid =
QtConcurrent::run([piece, pattern]() { return piece.IsSeamAllowanceValid(pattern); });
QFuture<QVector<VLayoutPoint>> futureMainPath =
QFuture<QVector<VLayoutPoint>> const futureMainPath =
QtConcurrent::run([piece, pattern]() { return piece.MainPathPoints(pattern); });
QFuture<QVector<VLayoutPiecePath>> futureInternalPaths = QtConcurrent::run(ConvertInternalPaths, piece, pattern);
QFuture<QVector<VLayoutPassmark>> futurePassmarks =
QFuture<QVector<VLayoutPiecePath>> const futureInternalPaths =
QtConcurrent::run(ConvertInternalPaths, piece, pattern);
QFuture<QVector<VLayoutPassmark>> const futurePassmarks =
QtConcurrent::run(VLayoutPiece::ConvertPassmarks, piece, pattern);
QFuture<QVector<VLayoutPlaceLabel>> futurePlaceLabels = QtConcurrent::run(ConvertPlaceLabels, piece, pattern);
QFuture<QVector<VLayoutPlaceLabel>> const futurePlaceLabels = QtConcurrent::run(ConvertPlaceLabels, piece, pattern);
VLayoutPiece det;
@ -582,6 +662,9 @@ auto VLayoutPiece::Create(const VPiece &piece, vidtype id, const VContainer *pat
det.SetForceFlipping(piece.IsForceFlipping());
det.SetFollowGrainline(piece.IsFollowGrainline());
det.SetSewLineOnDrawing(piece.IsSewLineOnDrawing());
det.SetShowFullPiece(piece.IsShowFullPiece());
det.SetSeamMirrorLine(piece.SeamMirrorLine(pattern));
det.SetSeamAllowanceMirrorLine(piece.SeamAllowanceMirrorLine(pattern));
det.SetId(id);
if (not futureSeamAllowanceValid.result())
@ -626,6 +709,8 @@ auto VLayoutPiece::Create(const VPiece &piece, vidtype id, const VContainer *pat
det.SetGrainline(grainlineGeom, pattern);
}
InitFoldLine(det, piece, pattern);
return det;
}
@ -648,8 +733,7 @@ auto VLayoutPiece::Map<VLayoutPassmark>(QVector<VLayoutPassmark> passmarks) cons
{
for (auto &passmark : passmarks)
{
passmark.lines = Map(passmark.lines);
passmark.baseLine = d->m_matrix.map(passmark.baseLine);
passmark = MapPassmark(passmark, d->m_matrix, d->m_verticallyFlipped || d->m_horizontallyFlipped);
}
return passmarks;
@ -659,14 +743,7 @@ auto VLayoutPiece::Map<VLayoutPassmark>(QVector<VLayoutPassmark> passmarks) cons
template <> auto VLayoutPiece::Map<VLayoutPoint>(QVector<VLayoutPoint> points) const -> QVector<VLayoutPoint>
{
std::transform(points.begin(), points.end(), points.begin(),
[this](VLayoutPoint point)
{
auto p = static_cast<QPointF>(point); // NOLINT(cppcoreguidelines-slicing)
p = d->m_matrix.map(p);
point.rx() = p.x();
point.ry() = p.y();
return point;
});
[this](const VLayoutPoint &point) { return MapPoint(point, d->m_matrix); });
if (d->m_verticallyFlipped || d->m_horizontallyFlipped)
{
std::reverse(points.begin(), points.end());
@ -694,6 +771,30 @@ auto VLayoutPiece::GetMappedContourPoints() const -> QVector<VLayoutPoint>
return Map(d->m_contour);
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetMappedFullContourPoints() const -> QVector<VLayoutPoint>
{
return Map(GetFullContourPoints());
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetFullContourPoints() const -> QVector<VLayoutPoint>
{
QVector<VLayoutPoint> points;
points.reserve(d->m_contour.size());
if (!d->m_seamMirrorLine.isNull() && IsShowFullPiece())
{
points = VAbstractPiece::FullPath(d->m_contour, d->m_seamMirrorLine);
points = CheckLoops(CorrectEquidistantPoints(points)); // A path can contains loops
}
else
{
points = d->m_contour;
}
return points;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetContourPoints() const -> QVector<VLayoutPoint>
{
@ -714,6 +815,30 @@ auto VLayoutPiece::GetMappedSeamAllowancePoints() const -> QVector<VLayoutPoint>
return Map(d->m_seamAllowance);
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetMappedFullSeamAllowancePoints() const -> QVector<VLayoutPoint>
{
return Map(GetFullSeamAllowancePoints());
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetFullSeamAllowancePoints() const -> QVector<VLayoutPoint>
{
QVector<VLayoutPoint> points;
points.reserve(d->m_seamAllowance.size());
if (!d->m_seamAllowanceMirrorLine.isNull() && IsShowFullPiece())
{
points = VAbstractPiece::FullPath(d->m_seamAllowance, d->m_seamAllowanceMirrorLine);
points = CheckLoops(CorrectEquidistantPoints(points)); // A path can contains loops
}
else
{
points = d->m_seamAllowance;
}
return points;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetSeamAllowancePoints() const -> QVector<VLayoutPoint>
{
@ -753,17 +878,6 @@ auto VLayoutPiece::GetLayoutAllowancePoints() const -> QVector<QPointF>
return d->m_layoutAllowance;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetPieceTextPosition() const -> QPointF
{
if (d->m_detailLabel.count() > 2)
{
return d->m_matrix.map(d->m_detailLabel.constFirst());
}
return {};
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetPieceText() const -> QStringList
{
@ -837,17 +951,6 @@ void VLayoutPiece::SetPieceLabelData(const VTextManager &data)
d->m_tmDetail = data;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetPatternTextPosition() const -> QPointF
{
if (d->m_patternInfo.count() > 2)
{
return d->m_matrix.map(d->m_patternInfo.constFirst());
}
return {};
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetPatternText() const -> QStringList
{
@ -919,6 +1022,102 @@ void VLayoutPiece::SetPatternLabelData(const VTextManager &data)
d->m_tmPattern = data;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetMappedSeamMirrorLine() const -> QLineF
{
return d->m_matrix.map(d->m_seamMirrorLine);
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetSeamMirrorLine() const -> QLineF
{
return d->m_seamMirrorLine;
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::SetSeamMirrorLine(const QLineF &line)
{
d->m_seamMirrorLine = line;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetMappedSeamAllowanceMirrorLine() const -> QLineF
{
return d->m_matrix.map(d->m_seamAllowanceMirrorLine);
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetSeamAllowanceMirrorLine() const -> QLineF
{
return d->m_seamAllowanceMirrorLine;
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::SetSeamAllowanceMirrorLine(const QLineF &line)
{
d->m_seamAllowanceMirrorLine = line;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetFoldLineHeight() const -> qreal
{
return d->m_foldLineHeight;
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::SetFoldLineHeight(qreal height)
{
d->m_foldLineHeight = height;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetFoldLineWidth() const -> qreal
{
return d->m_foldLineWidth;
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::SetFoldLineWidth(qreal width)
{
d->m_foldLineWidth = width;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetFoldLineCenterPosition() const -> qreal
{
return d->m_foldLineCenter;
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::SetFoldLineCenterPosition(qreal center)
{
d->m_foldLineCenter = center;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetFoldLineOutlineFont() const -> QFont
{
return d->m_foldLineOutlineFont;
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::SetFoldLineOutlineFont(const QFont &font)
{
d->m_foldLineOutlineFont = font;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetFoldLineSVGFontFamily() const -> QString
{
return d->m_foldLineSvgFontFamily;
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::SetFoldLineSVGFontFamily(const QString &font)
{
d->m_foldLineSvgFontFamily = font;
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::SetGrainline(const VPieceGrainline &grainline)
{
@ -1153,6 +1352,30 @@ auto VLayoutPiece::Diagonal() const -> qreal
return qSqrt(pow(rec.height(), 2) + pow(rec.width(), 2));
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::FoldLine() const -> VFoldLine
{
QLineF const foldLine = IsHideMainPath() ? GetSeamAllowanceMirrorLine() : GetSeamMirrorLine();
VFoldLine fLine(foldLine, GetFoldLineType());
fLine.SetLabelSvgFontSize(GetFoldLineSvgFontSize());
fLine.SetLabelFontItalic(IsFoldLineLabelFontItalic());
fLine.SetLabelFontBold(IsFoldLineLabelFontBold());
fLine.SetLabel(GetFoldLineLabel());
fLine.SetLabelAlignment(GetFoldLineLabelAlignment());
fLine.SetHeight(GetFoldLineHeight());
fLine.SetWidth(GetFoldLineWidth());
fLine.SetCenterPosition(GetFoldLineCenterPosition());
fLine.SetMatrix(GetMatrix());
fLine.SetHorizontallyFlipped(IsHorizontallyFlipped());
fLine.SetVerticallyFlipped(IsVerticallyFlipped());
fLine.SetXScale(GetXScale());
fLine.SetYScale(GetYScale());
fLine.SetOutlineFont(GetFoldLineOutlineFont());
fLine.SetSvgFont(GetFoldLineSVGFontFamily());
return fLine;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::isNull() const -> bool
{
@ -1177,8 +1400,8 @@ void VLayoutPiece::SetLayoutAllowancePoints(bool togetherWithNotches)
if (d->m_layoutWidth > 0)
{
QVector<VLayoutPoint> pieceBoundary = IsSeamAllowance() && not IsSeamAllowanceBuiltIn()
? GetMappedSeamAllowancePoints()
: GetMappedContourPoints();
? GetMappedFullSeamAllowancePoints()
: GetMappedFullContourPoints();
if (togetherWithNotches)
{
@ -1188,6 +1411,10 @@ void VLayoutPiece::SetLayoutAllowancePoints(bool togetherWithNotches)
VBoundary boundary(pieceBoundary, seamAllowance, builtInSeamAllowance);
boundary.SetPieceName(GetName());
if (IsShowFullPiece())
{
boundary.SetMirrorLine(GetMappedSeamAllowanceMirrorLine());
}
const QList<VBoundarySequenceItemData> sequence = boundary.Combine(passmarks, false, true);
pieceBoundary.clear();
@ -1220,14 +1447,14 @@ void VLayoutPiece::SetLayoutAllowancePoints(bool togetherWithNotches)
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetMappedExternalContourPoints() const -> QVector<VLayoutPoint>
{
return IsSeamAllowance() && not IsSeamAllowanceBuiltIn() ? GetMappedSeamAllowancePoints()
: GetMappedContourPoints();
return IsSeamAllowance() && not IsSeamAllowanceBuiltIn() ? GetMappedFullSeamAllowancePoints()
: GetMappedFullContourPoints();
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetExternalContourPoints() const -> QVector<VLayoutPoint>
{
return IsSeamAllowance() && not IsSeamAllowanceBuiltIn() ? GetSeamAllowancePoints() : GetContourPoints();
return IsSeamAllowance() && not IsSeamAllowanceBuiltIn() ? GetFullSeamAllowancePoints() : GetFullContourPoints();
}
//---------------------------------------------------------------------------------------------------------------------
@ -1264,16 +1491,18 @@ void VLayoutPiece::SetPlaceLabels(const QVector<VLayoutPlaceLabel> &labels)
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::MappedInternalPathsForCut(bool cut) const -> QVector<QVector<VLayoutPoint>>
auto VLayoutPiece::MappedInternalPathsForCut(bool cut) const -> QVector<VLayoutPiecePath>
{
QVector<QVector<VLayoutPoint>> paths;
QVector<VLayoutPiecePath> paths;
paths.reserve(d->m_internalPaths.size());
for (const auto &path : d->m_internalPaths)
{
if (path.IsCutPath() == cut)
{
paths.append(Map(path.Points()));
VLayoutPiecePath iPath = path;
iPath.SetPoints(Map(path.Points()));
paths.append(iPath);
}
}
@ -1311,8 +1540,12 @@ auto VLayoutPiece::ContourPath(bool togetherWithNotches, bool showLayoutAllowanc
bool seamAllowance = IsSeamAllowance() && IsSeamAllowanceBuiltIn();
bool builtInSeamAllowance = IsSeamAllowance() && IsSeamAllowanceBuiltIn();
VBoundary boundary(d->m_contour, seamAllowance, builtInSeamAllowance);
VBoundary boundary(GetFullContourPoints(), seamAllowance, builtInSeamAllowance);
boundary.SetPieceName(GetName());
if (IsShowFullPiece())
{
boundary.SetMirrorLine(d->m_seamMirrorLine);
}
const QList<VBoundarySequenceItemData> sequence = boundary.Combine(d->m_passmarks, true, false);
for (const auto &item : sequence)
@ -1325,7 +1558,7 @@ auto VLayoutPiece::ContourPath(bool togetherWithNotches, bool showLayoutAllowanc
}
else
{
path = VGObject::PainterPath(GetContourPoints());
path = VGObject::PainterPath(GetFullContourPoints());
}
}
@ -1337,8 +1570,12 @@ auto VLayoutPiece::ContourPath(bool togetherWithNotches, bool showLayoutAllowanc
// Draw seam allowance
if (togetherWithNotches)
{
VBoundary boundary(d->m_seamAllowance, true);
VBoundary boundary(GetFullSeamAllowancePoints(), true);
boundary.SetPieceName(GetName());
if (IsShowFullPiece())
{
boundary.SetMirrorLine(d->m_seamAllowanceMirrorLine);
}
const QList<VBoundarySequenceItemData> sequence = boundary.Combine(d->m_passmarks, true, false);
for (const auto &item : sequence)
@ -1351,7 +1588,7 @@ auto VLayoutPiece::ContourPath(bool togetherWithNotches, bool showLayoutAllowanc
}
else
{
QVector<VLayoutPoint> points = d->m_seamAllowance;
QVector<VLayoutPoint> points = GetFullSeamAllowancePoints();
if (points.constLast().toPoint() != points.constFirst().toPoint())
{
points.append(points.at(0)); // Should be always closed
@ -1364,16 +1601,32 @@ auto VLayoutPiece::ContourPath(bool togetherWithNotches, bool showLayoutAllowanc
if (!togetherWithNotches)
{
// Draw passmarks
QPainterPath passmaksPath;
for (const auto &passmark : d->m_passmarks)
{
QPainterPath passmaksPath;
for (const auto &line : passmark.lines)
{
passmaksPath.moveTo(line.p1());
passmaksPath.lineTo(line.p2());
}
}
path.addPath(passmaksPath);
if (!d->m_seamAllowanceMirrorLine.isNull() && IsShowFullPiece())
{
if (!VGObject::IsPointOnLineviaPDP(passmark.baseLine.p1(), d->m_seamAllowanceMirrorLine.p1(),
d->m_seamAllowanceMirrorLine.p2()))
{
QPainterPath mirroredPassmaksPath;
for (const auto &line : passmark.lines)
{
mirroredPassmaksPath.moveTo(line.p1());
mirroredPassmaksPath.lineTo(line.p2());
}
const QTransform matrix = VGObject::FlippingMatrix(d->m_seamAllowanceMirrorLine);
path.addPath(matrix.map(mirroredPassmaksPath));
}
}
}
}
path.setFillRule(Qt::WindingFill);
@ -1428,7 +1681,21 @@ auto VLayoutPiece::GetItem(bool textAsPaths, bool togetherWithNotches, bool show
for (const auto &path : d->m_internalPaths)
{
auto *pathItem = new QGraphicsPathItem(item);
pathItem->setPath(d->m_matrix.map(path.GetPainterPath()));
QPainterPath p = d->m_matrix.map(path.GetPainterPath());
if (!path.IsNotMirrored() && IsShowFullPiece() && !d->m_seamMirrorLine.isNull())
{
QVector<VLayoutPoint> points = path.Points();
const QTransform matrix = VGObject::FlippingMatrix(d->m_seamMirrorLine);
std::transform(points.begin(), points.end(), points.begin(),
[matrix](const VLayoutPoint &point) { return VAbstractPiece::MapPoint(point, matrix); });
QVector<QPointF> casted;
CastTo(points, casted);
p.addPath(d->m_matrix.map(VPiecePath::MakePainterPath(casted)));
}
pathItem->setPath(p);
QPen pen = pathItem->pen();
pen.setStyle(path.PenStyle());
@ -1442,12 +1709,68 @@ auto VLayoutPiece::GetItem(bool textAsPaths, bool togetherWithNotches, bool show
QPen pen = pathItem->pen();
pen.setWidthF(VAbstractApplication::VApp()->Settings()->WidthHairLine());
pathItem->setPen(pen);
pathItem->setPath(d->m_matrix.map(LabelShapePath(PlaceLabelShape(label))));
QPainterPath path;
path.addPath(d->m_matrix.map(LabelShapePath(label)));
if (!label.IsNotMirrored() && IsShowFullPiece() && !d->m_seamMirrorLine.isNull())
{
PlaceLabelImg shape = VAbstractPiece::PlaceLabelShape(label);
const QTransform matrix = VGObject::FlippingMatrix(d->m_seamMirrorLine);
for (auto &points : shape)
{
std::transform(points.begin(), points.end(), points.begin(),
[matrix](const VLayoutPoint &point) { return MapPoint(point, matrix); });
}
path.addPath(d->m_matrix.map(LabelShapePath(shape)));
}
pathItem->setPath(path);
}
CreateLabelStrings(item, d->m_detailLabel, d->m_tmDetail, textAsPaths);
CreateLabelStrings(item, d->m_patternInfo, d->m_tmPattern, textAsPaths);
CreateGrainlineItem(item);
CreateFoldLineItem(item, textAsPaths);
if (IsShowFullPiece())
{
bool mirrorFlag = false;
QPainterPath mirrorLinePath;
if (not IsSeamAllowance() || IsSeamAllowanceBuiltIn())
{
if (!d->m_seamMirrorLine.isNull())
{
QPainterPath mirrorPath;
mirrorPath.moveTo(d->m_matrix.map(d->m_seamMirrorLine.p1()));
mirrorPath.lineTo(d->m_matrix.map(d->m_seamMirrorLine.p2()));
mirrorLinePath.addPath(mirrorPath);
mirrorFlag = true;
}
}
else if (not IsSeamAllowanceBuiltIn())
{
if (!d->m_seamAllowanceMirrorLine.isNull())
{
QPainterPath mirrorPath;
mirrorPath.moveTo(d->m_matrix.map(d->m_seamAllowanceMirrorLine.p1()));
mirrorPath.lineTo(d->m_matrix.map(d->m_seamAllowanceMirrorLine.p2()));
mirrorLinePath.addPath(mirrorPath);
mirrorFlag = true;
}
}
if (mirrorFlag)
{
auto *mirrorLineItem = new QGraphicsPathItem(item);
QPen pen = mirrorLineItem->pen();
pen.setWidthF(VAbstractApplication::VApp()->Settings()->WidthHairLine());
pen.setStyle(Qt::DashDotLine);
mirrorLineItem->setPen(pen);
mirrorLineItem->setPath(mirrorLinePath);
}
}
return item;
}
@ -1456,7 +1779,7 @@ auto VLayoutPiece::GetItem(bool textAsPaths, bool togetherWithNotches, bool show
auto VLayoutPiece::IsLayoutAllowanceValid(bool togetherWithNotches) const -> bool
{
QVector<VLayoutPoint> base =
(IsSeamAllowance() && not IsSeamAllowanceBuiltIn()) ? d->m_seamAllowance : d->m_contour;
(IsSeamAllowance() && not IsSeamAllowanceBuiltIn()) ? GetFullSeamAllowancePoints() : GetFullContourPoints();
if (togetherWithNotches)
{
@ -1466,6 +1789,10 @@ auto VLayoutPiece::IsLayoutAllowanceValid(bool togetherWithNotches) const -> boo
VBoundary boundary(base, seamAllowance, builtInSeamAllowance);
boundary.SetPieceName(GetName());
if (IsShowFullPiece())
{
boundary.SetMirrorLine(d->m_seamAllowanceMirrorLine);
}
const QList<VBoundarySequenceItemData> sequence = boundary.Combine(passmarks, false, true);
base.clear();
@ -1516,6 +1843,14 @@ auto VLayoutPiece::MapPlaceLabelShape(PlaceLabelImg shape) const -> PlaceLabelIm
return shape;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::MapPassmark(VLayoutPassmark passmark, const QTransform &matrix, bool mirror) -> VLayoutPassmark
{
passmark.lines = MapVector(passmark.lines, matrix, mirror);
passmark.baseLine = matrix.map(passmark.baseLine);
return passmark;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::BoundingRect(QVector<QPointF> points) -> QRectF
{
@ -1589,7 +1924,6 @@ void VLayoutPiece::LabelStringsSVGFont(QGraphicsItem *parent, const QVector<QPoi
break;
}
QString qsText = tl.m_qsText;
qreal dX = 0;
if (tl.m_eAlign == 0 || (tl.m_eAlign & Qt::AlignLeft) > 0)
{
@ -1597,11 +1931,11 @@ void VLayoutPiece::LabelStringsSVGFont(QGraphicsItem *parent, const QVector<QPoi
}
else if ((tl.m_eAlign & Qt::AlignHCenter) > 0)
{
dX = (dW - engine.TextWidth(qsText, penWidth)) / 2;
dX = (dW - engine.TextWidth(tl.m_qsText, penWidth)) / 2;
}
else if ((tl.m_eAlign & Qt::AlignRight) > 0)
{
dX = dW - engine.TextWidth(qsText, penWidth);
dX = dW - engine.TextWidth(tl.m_qsText, penWidth);
}
// set up the rotation around top-left corner matrix
@ -1630,11 +1964,11 @@ void VLayoutPiece::LabelStringsSVGFont(QGraphicsItem *parent, const QVector<QPoi
pen.setWidthF(penWidth);
item->setPen(pen);
item->setPath(engine.DrawPath(QPointF(), qsText));
item->setPath(engine.DrawPath(QPointF(), tl.m_qsText));
item->setBrush(QBrush(Qt::NoBrush));
item->setTransform(labelMatrix);
dY += engine.FontHeight() + penWidth + tm.GetSpacing();
dY += engine.FontHeight() - penWidth * 2 + tm.GetSpacing();
}
}
@ -1686,7 +2020,6 @@ void VLayoutPiece::LabelStringsOutlineFont(QGraphicsItem *parent, const QVector<
break;
}
QString qsText = tl.m_qsText;
qreal dX = 0;
if (tl.m_eAlign == 0 || (tl.m_eAlign & Qt::AlignLeft) > 0)
{
@ -1694,11 +2027,11 @@ void VLayoutPiece::LabelStringsOutlineFont(QGraphicsItem *parent, const QVector<
}
else if ((tl.m_eAlign & Qt::AlignHCenter) > 0)
{
dX = (dW - TextWidth(fm, qsText)) / 2;
dX = (dW - TextWidth(fm, tl.m_qsText)) / 2;
}
else if ((tl.m_eAlign & Qt::AlignRight) > 0)
{
dX = dW - TextWidth(fm, qsText);
dX = dW - TextWidth(fm, tl.m_qsText);
}
// set up the rotation around top-left corner matrix
@ -1708,15 +2041,14 @@ void VLayoutPiece::LabelStringsOutlineFont(QGraphicsItem *parent, const QVector<
{
labelMatrix.scale(-1, 1);
labelMatrix.rotate(-angle);
labelMatrix.translate(-dW, 0);
labelMatrix.translate(dX, dY); // Each string has own position
labelMatrix.translate(-tm.MaxLineWidthOutlineFont(static_cast<int>(dW)), 0);
}
else
{
labelMatrix.rotate(angle);
labelMatrix.translate(dX, dY); // Each string has own position
}
labelMatrix.translate(dX, dY); // Each string has own position
labelMatrix *= d->m_matrix;
if (textAsPaths)
@ -1726,7 +2058,7 @@ void VLayoutPiece::LabelStringsOutlineFont(QGraphicsItem *parent, const QVector<
if (settings->GetSingleStrokeOutlineFont())
{
int w = 0;
for (auto c : qAsConst(qsText))
for (auto c : qAsConst(tl.m_qsText))
{
path.addPath(corrector.DrawChar(w, static_cast<qreal>(fm.ascent()), c));
w += TextWidth(fm, c);
@ -1734,7 +2066,7 @@ void VLayoutPiece::LabelStringsOutlineFont(QGraphicsItem *parent, const QVector<
}
else
{
path.addText(0, static_cast<qreal>(fm.ascent()), fnt, qsText);
path.addText(0, static_cast<qreal>(fm.ascent()), fnt, tl.m_qsText);
}
auto *item = new QGraphicsPathItem(parent);
@ -1749,16 +2081,16 @@ void VLayoutPiece::LabelStringsOutlineFont(QGraphicsItem *parent, const QVector<
item->setBrush(settings->GetSingleStrokeOutlineFont() ? QBrush(Qt::NoBrush) : QBrush(Qt::black));
item->setTransform(labelMatrix);
dY += fm.height() + penWidth + tm.GetSpacing();
dY += fm.height() + penWidth * 2 + MmToPixel(1.5) + tm.GetSpacing();
}
else
{
auto *item = new QGraphicsSimpleTextItem(parent);
item->setFont(fnt);
item->setText(qsText);
item->setText(tl.m_qsText);
item->setTransform(labelMatrix);
dY += (fm.height() + tm.GetSpacing());
dY += (fm.height() + MmToPixel(1.5) + tm.GetSpacing());
}
}
}
@ -1797,6 +2129,83 @@ void VLayoutPiece::CreateGrainlineItem(QGraphicsItem *parent) const
item->setPen(pen);
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::CreateFoldLineItem(QGraphicsItem *parent, bool textAsPaths) const
{
SCASSERT(parent != nullptr)
if (GetFoldLineType() == FoldLineType::None)
{
return;
}
VFoldLine const fLine = FoldLine();
QVector<QPainterPath> const shape = fLine.FoldLinePath();
if (shape.isEmpty())
{
return;
}
VCommonSettings *settings = VAbstractApplication::VApp()->Settings();
if (!textAsPaths && !settings->GetSingleStrokeOutlineFont() && !settings->GetSingleLineFonts())
{
auto *item = new QGraphicsSimpleTextItem(parent);
fLine.UpdateFoldLineLabel(item);
}
auto FoldLineMark = [parent](const QPainterPath &shape)
{
auto *item = new VGraphicsFoldLineItem(shape, parent);
item->SetCustomPen(true);
QPen pen = item->pen();
pen.setWidthF(VAbstractApplication::VApp()->Settings()->WidthHairLine());
pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::RoundJoin);
item->setPen(pen);
};
auto FoldLineLabel = [parent](const QPainterPath &shape)
{
auto *item = new QGraphicsPathItem(parent);
item->setPath(shape);
VCommonSettings *settings = VAbstractApplication::VApp()->Settings();
QPen itemPen = item->pen();
itemPen.setColor(Qt::black);
itemPen.setCapStyle(Qt::RoundCap);
itemPen.setJoinStyle(Qt::RoundJoin);
itemPen.setWidthF(settings->WidthHairLine());
item->setPen(itemPen);
item->setBrush(settings->GetSingleStrokeOutlineFont() || settings->GetSingleLineFonts() ? QBrush(Qt::NoBrush)
: QBrush(Qt::black));
};
if (GetFoldLineType() == FoldLineType::ThreeDots || GetFoldLineType() == FoldLineType::ThreeX ||
GetFoldLineType() == FoldLineType::TwoArrows)
{
FoldLineMark(shape.constFirst());
}
else if (GetFoldLineType() == FoldLineType::Text)
{
if (settings->GetSingleStrokeOutlineFont() || settings->GetSingleLineFonts())
{
FoldLineLabel(shape.constFirst());
}
}
else
{
FoldLineMark(shape.constFirst());
if (shape.size() > 1 && (settings->GetSingleStrokeOutlineFont() || settings->GetSingleLineFonts()))
{
FoldLineLabel(shape.constLast());
}
}
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::DetailPath() const -> QVector<VLayoutPoint>
{
@ -1830,7 +2239,7 @@ auto VLayoutPiece::GetMainPathItem() const -> QGraphicsPathItem *
QPainterPath path;
// contour
QVector<VLayoutPoint> points = GetMappedContourPoints();
QVector<VLayoutPoint> const points = GetMappedContourPoints();
path.moveTo(points.at(0));
for (qint32 i = 1; i < points.count(); ++i)

View File

@ -63,16 +63,7 @@ class VPieceLabelData;
class VAbstractPattern;
class VPatternLabelData;
class VLayoutPoint;
template <typename T> struct IsLayoutPoint
{
static const bool value = false;
};
template <> struct IsLayoutPoint<VLayoutPoint>
{
static const bool value = true;
};
class VFoldLine;
QT_WARNING_PUSH
QT_WARNING_DISABLE_GCC("-Wsuggest-final-types")
@ -100,10 +91,14 @@ public:
auto GetUniqueID() const -> QString override;
auto GetMappedContourPoints() const -> QVector<VLayoutPoint>;
auto GetMappedFullContourPoints() const -> QVector<VLayoutPoint>;
auto GetFullContourPoints() const -> QVector<VLayoutPoint>;
auto GetContourPoints() const -> QVector<VLayoutPoint>;
void SetContourPoints(const QVector<VLayoutPoint> &points, bool hideMainPath = false);
auto GetMappedSeamAllowancePoints() const -> QVector<VLayoutPoint>;
auto GetMappedFullSeamAllowancePoints() const -> QVector<VLayoutPoint>;
auto GetFullSeamAllowancePoints() const -> QVector<VLayoutPoint>;
auto GetSeamAllowancePoints() const -> QVector<VLayoutPoint>;
void SetSeamAllowancePoints(const QVector<VLayoutPoint> &points, bool seamAllowance = true,
bool seamAllowanceBuiltIn = false);
@ -122,16 +117,14 @@ public:
auto GetPlaceLabels() const -> QVector<VLayoutPlaceLabel>;
void SetPlaceLabels(const QVector<VLayoutPlaceLabel> &labels);
auto MappedInternalPathsForCut(bool cut) const -> QVector<QVector<VLayoutPoint>>;
auto MappedInternalPathsForCut(bool cut) const -> QVector<VLayoutPiecePath>;
auto GetInternalPaths() const -> QVector<VLayoutPiecePath>;
void SetInternalPaths(const QVector<VLayoutPiecePath> &internalPaths);
auto GetPieceTextPosition() const -> QPointF;
auto GetPieceText() const -> QStringList;
void SetPieceText(const QString &qsName, const VPieceLabelData &data, const QFont &font,
const QString &SVGFontFamily, const VContainer *pattern);
auto GetPatternTextPosition() const -> QPointF;
auto GetPatternText() const -> QStringList;
void SetPatternInfo(VAbstractPattern *pDoc, const VPatternLabelData &geom, const QFont &font,
const QString &SVGFontFamily, const VContainer *pattern);
@ -183,6 +176,29 @@ public:
auto GetPatternLabelData() const -> VTextManager;
void SetPatternLabelData(const VTextManager &data);
auto GetMappedSeamMirrorLine() const -> QLineF;
auto GetSeamMirrorLine() const -> QLineF;
void SetSeamMirrorLine(const QLineF &line);
auto GetMappedSeamAllowanceMirrorLine() const -> QLineF;
auto GetSeamAllowanceMirrorLine() const -> QLineF;
void SetSeamAllowanceMirrorLine(const QLineF &line);
auto GetFoldLineHeight() const -> qreal;
void SetFoldLineHeight(qreal height);
auto GetFoldLineWidth() const -> qreal;
void SetFoldLineWidth(qreal width);
auto GetFoldLineCenterPosition() const -> qreal;
void SetFoldLineCenterPosition(qreal center);
auto GetFoldLineOutlineFont() const -> QFont;
void SetFoldLineOutlineFont(const QFont &font);
auto GetFoldLineSVGFontFamily() const -> QString;
void SetFoldLineSVGFontFamily(const QString &font);
void Translate(const QPointF &p);
void Translate(qreal dx, qreal dy);
void Scale(qreal sx, qreal sy);
@ -201,6 +217,8 @@ public:
auto MappedLayoutBoundingRect() const -> QRectF;
auto Diagonal() const -> qreal;
auto FoldLine() const -> VFoldLine;
static auto BoundingRect(QVector<QPointF> points) -> QRectF;
static auto GrainlinePath(const GrainlineShape &shape) -> QPainterPath;
@ -226,14 +244,7 @@ public:
auto MapPlaceLabelShape(PlaceLabelImg shape) const -> PlaceLabelImg;
template <class T>
static auto MapVector(QVector<T> points, const QTransform &matrix, bool mirror = false) -> QVector<T>;
template <class T>
static auto MapPoint(T obj, const QTransform &matrix) -> typename std::enable_if<!IsLayoutPoint<T>::value, T>::type;
template <class T>
static auto MapPoint(T obj, const QTransform &matrix) -> typename std::enable_if<IsLayoutPoint<T>::value, T>::type;
static auto MapPassmark(VLayoutPassmark passmark, const QTransform &matrix, bool mirror) -> VLayoutPassmark;
protected:
void SetGrainline(const VPieceGrainline &grainline);
@ -254,6 +265,7 @@ private:
void CreateLabelStrings(QGraphicsItem *parent, const QVector<QPointF> &labelShape, const VTextManager &tm,
bool textAsPaths) const;
void CreateGrainlineItem(QGraphicsItem *parent) const;
void CreateFoldLineItem(QGraphicsItem *parent, bool textAsPaths) const;
template <class T> auto Map(QVector<T> points) const -> QVector<T>;
auto Map(const GrainlineShape &shape) const -> GrainlineShape;
@ -266,36 +278,4 @@ QT_WARNING_POP
Q_DECLARE_TYPEINFO(VLayoutPiece, Q_MOVABLE_TYPE); // NOLINT
//---------------------------------------------------------------------------------------------------------------------
template <class T>
inline auto VLayoutPiece::MapVector(QVector<T> points, const QTransform &matrix, bool mirror) -> QVector<T>
{
std::transform(points.begin(), points.end(), points.begin(),
[matrix](const T &point) { return MapPoint(point, matrix); });
if (mirror)
{
std::reverse(points.begin(), points.end());
}
return points;
}
//---------------------------------------------------------------------------------------------------------------------
template <typename T>
auto VLayoutPiece::MapPoint(T obj, const QTransform &matrix) ->
typename std::enable_if<!IsLayoutPoint<T>::value, T>::type
{
return matrix.map(obj);
}
//---------------------------------------------------------------------------------------------------------------------
template <typename T>
auto VLayoutPiece::MapPoint(T obj, const QTransform &matrix) ->
typename std::enable_if<IsLayoutPoint<T>::value, T>::type
{
auto p = matrix.map(obj);
obj.setX(p.x());
obj.setY(p.y());
return obj;
}
#endif // VLAYOUTDETAIL_H

View File

@ -115,11 +115,21 @@ public:
qreal m_xScale{1.0}; // NOLINT(misc-non-private-member-variables-in-classes)
qreal m_yScale{1.0}; // NOLINT(misc-non-private-member-variables-in-classes)
QLineF m_seamMirrorLine{}; // NOLINT(misc-non-private-member-variables-in-classes)
QLineF m_seamAllowanceMirrorLine{}; // NOLINT(misc-non-private-member-variables-in-classes)
qreal m_foldLineHeight{0}; // NOLINT(misc-non-private-member-variables-in-classes)
qreal m_foldLineWidth{0}; // NOLINT(misc-non-private-member-variables-in-classes)
qreal m_foldLineCenter{0.5}; // NOLINT(misc-non-private-member-variables-in-classes)
QFont m_foldLineOutlineFont{}; // NOLINT (misc-non-private-member-variables-in-classes)
QString m_foldLineSvgFontFamily{}; // NOLINT (misc-non-private-member-variables-in-classes)
private:
Q_DISABLE_ASSIGN_MOVE(VLayoutPieceData) // NOLINT
static constexpr quint32 streamHeader{0x80D7D009}; // CRC-32Q string "VLayoutPieceData"
static constexpr quint16 classVersion{6};
static constexpr quint16 classVersion{7};
};
QT_WARNING_POP
@ -157,6 +167,13 @@ inline auto operator<<(QDataStream &dataStream, const VLayoutPieceData &piece) -
dataStream << piece.m_yScale;
dataStream << piece.m_grainline;
dataStream << piece.m_horizontallyFlipped;
dataStream << piece.m_seamMirrorLine;
dataStream << piece.m_seamAllowanceMirrorLine;
dataStream << piece.m_foldLineHeight;
dataStream << piece.m_foldLineWidth;
dataStream << piece.m_foldLineCenter;
dataStream << piece.m_foldLineOutlineFont;
dataStream << piece.m_foldLineSvgFontFamily;
return dataStream;
}
@ -275,6 +292,17 @@ inline auto operator>>(QDataStream &dataStream, VLayoutPieceData &piece) -> QDat
dataStream >> piece.m_horizontallyFlipped;
}
if (actualClassVersion >= 7)
{
dataStream >> piece.m_seamMirrorLine;
dataStream >> piece.m_seamAllowanceMirrorLine;
dataStream >> piece.m_foldLineHeight;
dataStream >> piece.m_foldLineWidth;
dataStream >> piece.m_foldLineCenter;
dataStream >> piece.m_foldLineOutlineFont;
dataStream >> piece.m_foldLineSvgFontFamily;
}
return dataStream;
}

View File

@ -139,3 +139,15 @@ void VLayoutPiecePath::SetCutPath(bool cut)
{
d->m_cut = cut;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiecePath::IsNotMirrored() const -> bool
{
return d->m_notMirrored;
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiecePath::SetNotMirrored(bool value)
{
d->m_notMirrored = value;
}

View File

@ -63,6 +63,9 @@ public:
auto IsCutPath() const -> bool;
void SetCutPath(bool cut);
auto IsNotMirrored() const -> bool;
void SetNotMirrored(bool value);
friend auto operator<<(QDataStream &dataStream, const VLayoutPiecePath &path) -> QDataStream &;
friend auto operator>>(QDataStream &dataStream, VLayoutPiecePath &path) -> QDataStream &;

View File

@ -63,12 +63,13 @@ public:
Qt::PenStyle m_penStyle{Qt::SolidLine}; // NOLINT(misc-non-private-member-variables-in-classes)
bool m_cut{false}; // NOLINT(misc-non-private-member-variables-in-classes)
bool m_notMirrored{false}; // NOLINT(misc-non-private-member-variables-in-classes)
private:
Q_DISABLE_ASSIGN_MOVE(VLayoutPiecePathData) // NOLINT
static constexpr quint32 streamHeader = 0xA53F0225; // CRC-32Q string "VLayoutPiecePathData"
static constexpr quint16 classVersion = 2;
static constexpr quint16 classVersion = 3;
};
QT_WARNING_POP
@ -87,7 +88,7 @@ inline VLayoutPiecePathData::VLayoutPiecePathData(const QVector<VLayoutPoint> &p
// Friend functions
//---------------------------------------------------------------------------------------------------------------------
auto operator<<(QDataStream &dataStream, const VLayoutPiecePathData &path) -> QDataStream &
inline auto operator<<(QDataStream &dataStream, const VLayoutPiecePathData &path) -> QDataStream &
{
dataStream << VLayoutPiecePathData::streamHeader << VLayoutPiecePathData::classVersion;
@ -96,13 +97,14 @@ auto operator<<(QDataStream &dataStream, const VLayoutPiecePathData &path) -> QD
dataStream << path.m_penStyle;
dataStream << path.m_cut;
// Added in classVersion = 2
// Added in classVersion = 3
dataStream << path.m_notMirrored;
return dataStream;
}
//---------------------------------------------------------------------------------------------------------------------
auto operator>>(QDataStream &dataStream, VLayoutPiecePathData &path) -> QDataStream &
inline auto operator>>(QDataStream &dataStream, VLayoutPiecePathData &path) -> QDataStream &
{
quint32 actualStreamHeader = 0;
dataStream >> actualStreamHeader;
@ -141,10 +143,10 @@ auto operator>>(QDataStream &dataStream, VLayoutPiecePathData &path) -> QDataStr
dataStream >> path.m_penStyle;
dataStream >> path.m_cut;
// if (actualClassVersion >= 2)
// {
// }
if (actualClassVersion >= 3)
{
dataStream >> path.m_notMirrored;
}
return dataStream;
}

View File

@ -68,7 +68,7 @@ QPainterPath ShowDirection(const QLineF &edge)
arrow.setLength(edge.length() / 2.0);
// Reverse line because we want start arrow from this point
arrow = QLineF(arrow.p2(), arrow.p1());
Swap(arrow);
const qreal angle = arrow.angle(); // we each time change line angle, better save original angle value
arrow.setLength(arrowLength); // arrow length in pixels

View File

@ -44,17 +44,17 @@
#include "../vmisc/svgfont/vsvgfontengine.h"
#include "../vmisc/vabstractvalapplication.h"
#include "../vmisc/vcommonsettings.h"
#include "../vmisc/vtranslator.h"
#include "../vpatterndb/calculator.h"
#include "../vpatterndb/floatItemData/vpiecelabeldata.h"
#include "../vpatterndb/variables/vmeasurement.h"
#include "../vpatterndb/vcontainer.h"
#include "vtextmanager.h"
#if QT_VERSION < QT_VERSION_CHECK(5, 9, 0)
#include "../vmisc/vdatastreamenum.h"
#endif
#include "../vpatterndb/calculator.h"
#include "../vpatterndb/variables/vmeasurement.h"
#include "../vpatterndb/vcontainer.h"
#include "vtextmanager.h"
using namespace Qt::Literals::StringLiterals;
namespace
@ -471,7 +471,7 @@ auto PreparePlaceholders(const VAbstractPattern *doc, const VContainer *data, bo
QMap<QString, QString> placeholders;
// Pattern tags
QLocale locale(VAbstractApplication::VApp()->Settings()->GetLocale());
QLocale const locale(VAbstractApplication::VApp()->Settings()->GetLocale());
const QString date = locale.toString(QDate::currentDate(), doc->GetLabelDateFormat());
placeholders.insert(pl_date, date);
@ -516,7 +516,7 @@ auto PreparePlaceholders(const VAbstractPattern *doc, const VContainer *data, bo
placeholders.insert(pl_pQuantity, QString());
placeholders.insert(pl_wOnFold, QString());
QSharedPointer<QTranslator> phTr = VAbstractValApplication::VApp()->GetPlaceholderTranslator();
QSharedPointer<VTranslator> const phTr = VAbstractApplication::VApp()->GetPlaceholderTranslator();
placeholders.insert(pl_mFabric, phTr->translate("Placeholder", "Fabric"));
placeholders.insert(pl_mLining, phTr->translate("Placeholder", "Lining"));
@ -541,7 +541,7 @@ void InitPiecePlaceholders(QMap<QString, QString> &placeholders, const QString &
if (data.IsOnFold())
{
QSharedPointer<QTranslator> phTr = VAbstractValApplication::VApp()->GetPlaceholderTranslator();
QSharedPointer<VTranslator> phTr = VAbstractApplication::VApp()->GetPlaceholderTranslator();
placeholders[pl_wOnFold] = phTr->translate("Placeholder", "on fold");
}
}

View File

@ -418,11 +418,9 @@ auto PassmarkAngleTypeToString(PassmarkAngleType type) -> QString
case PassmarkAngleType::Intersection2OnlyRight:
return strIntersection2OnlyRight;
default:
break;
}
return strStraightforward;
}
}
//---------------------------------------------------------------------------------------------------------------------
auto StringToPassmarkAngleType(const QString &value) -> PassmarkAngleType
@ -450,10 +448,63 @@ auto StringToPassmarkAngleType(const QString &value) -> PassmarkAngleType
case 7:
return PassmarkAngleType::Intersection2OnlyRight;
default:
break;
}
return PassmarkAngleType::Straightforward;
}
}
//---------------------------------------------------------------------------------------------------------------------
auto FoldLineTypeToString(FoldLineType type) -> QString
{
switch (type)
{
case FoldLineType::TwoArrowsTextUnder:
return strFoldTypeTwoArrowsTextUnder;
case FoldLineType::TwoArrows:
return strFoldTypeTwoArrows;
case FoldLineType::Text:
return strFoldTypeText;
case FoldLineType::ThreeDots:
return strFoldTypeThreeDots;
case FoldLineType::ThreeX:
return strFoldTypeThreeX;
case FoldLineType::None:
return strFoldTypeNone;
case FoldLineType::TwoArrowsTextAbove:
default:
return strFoldTypeTwoArrowsTextAbove;
}
}
//---------------------------------------------------------------------------------------------------------------------
auto StringToFoldLineType(const QString &value) -> FoldLineType
{
const QStringList values{strFoldTypeTwoArrowsTextAbove, // 0
strFoldTypeTwoArrowsTextUnder, // 1
strFoldTypeTwoArrows, // 2
strFoldTypeText, // 3
strFoldTypeThreeDots, // 4
strFoldTypeThreeX, // 5
strFoldTypeNone}; // 6
switch (values.indexOf(value))
{
case 1:
return FoldLineType::TwoArrowsTextUnder;
case 2:
return FoldLineType::TwoArrows;
case 3:
return FoldLineType::Text;
case 4:
return FoldLineType::ThreeDots;
case 5:
return FoldLineType::ThreeX;
case 6:
return FoldLineType::None;
case 0:
default:
return FoldLineType::TwoArrowsTextAbove;
};
}
//---------------------------------------------------------------------------------------------------------------------
auto StrToUnits(const QString &unit) -> Unit

View File

@ -211,6 +211,23 @@ enum class PiecePathIncludeType : quint8
AsCustomSA = 1
};
constexpr unsigned int defFoldLineFontSize{12};
enum class FoldLineType : quint8
{
TwoArrowsTextAbove = 0, // Default
TwoArrowsTextUnder,
TwoArrows,
Text,
ThreeDots,
ThreeX,
None,
LAST_ONE_DO_NOT_USE
};
auto FoldLineTypeToString(FoldLineType type) -> QString;
auto StringToFoldLineType(const QString &value) -> FoldLineType;
enum class PiecePathType : quint8
{
PiecePath = 0,
@ -348,6 +365,7 @@ enum class Vis : ToolVisHolderType
enum class Layout : ToolVisHolderType
{
GrainlineItem = static_cast<ToolVisHolderType>(Vis::LAST_ONE_DO_NOT_USE),
FoldLineItem,
LAST_ONE_DO_NOT_USE // add new stuffs above this, this constant must be last and never used
};

View File

@ -160,6 +160,13 @@ const QString strIntersection2OnlyRight = QStringLiteral("intersection2Right");
const QString strTypeIncrement = QStringLiteral("increment");
const QString strTypeSeparator = QStringLiteral("separator");
const QString strTypeMeasurement = QStringLiteral("measurement");
const QString strFoldTypeTwoArrowsTextAbove = QStringLiteral("2ArrowsTextAbove");
const QString strFoldTypeTwoArrowsTextUnder = QStringLiteral("2ArrowsTextUnder");
const QString strFoldTypeTwoArrows = QStringLiteral("2Arrows");
const QString strFoldTypeText = QStringLiteral("text");
const QString strFoldTypeThreeDots = QStringLiteral("3dots");
const QString strFoldTypeThreeX = QStringLiteral("3X");
const QString strFoldTypeNone = QStringLiteral("none");
const QString unitMM = QStringLiteral("mm");
const QString unitCM = QStringLiteral("cm");

View File

@ -164,6 +164,13 @@ extern const QString strIntersection2OnlyRight;
extern const QString strTypeIncrement;
extern const QString strTypeSeparator;
extern const QString strTypeMeasurement;
extern const QString strFoldTypeTwoArrowsTextAbove;
extern const QString strFoldTypeTwoArrowsTextUnder;
extern const QString strFoldTypeTwoArrows;
extern const QString strFoldTypeText;
extern const QString strFoldTypeThreeDots;
extern const QString strFoldTypeThreeX;
extern const QString strFoldTypeNone;
extern const QString unitMM;
extern const QString unitCM;

View File

@ -213,5 +213,7 @@
<file>icon/light/16x16/viewimage.png</file>
<file>icon/dark/16x16/viewimage.png</file>
<file>icon/dark/16x16/viewimage@2x.png</file>
<file>icon/32x32/fold.png</file>
<file>icon/32x32/fold@2x.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 827 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -31,6 +31,7 @@
},
"ManualLayoutStyle": {
"SheetBorderColor": "#808080",
"SheetFoldShadowColor": "#6699cc",
"SheetMarginColor": "#00b3ff",
"SheetGridColor": "#cccccc",
"SheetTileGridColor": "#80ff0000",
@ -40,6 +41,7 @@
"PieceHoverColor": "#80c7f4f9",
"PieceHandleColor": "#add8e6",
"PieceHandleHoverColor": "#90ee90",
"PieceSelectionBrushColor": [255, 160, 160, 60],
"CarrouselPieceColor": "#78a0c8",
"CarrouselPieceSelectedColor": "#80ffa0a0",
"CarrouselPieceBackgroundColor": "#202020",

Some files were not shown because too many files have changed in this diff Show More