From 83c914f47d964ec74f4d8bac5dbd88fd7c38360b Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Mon, 10 Jul 2023 19:23:41 +0300 Subject: [PATCH] Export to HP-GL format. --- ChangeLog.txt | 1 + dist/OBS_debian/debian.valentina.1 | 13 +- dist/debian/valentina.1 | 13 +- .../puzzle/dialogs/dialogsavemanuallayout.cpp | 56 +- .../puzzle/dialogs/dialogsavemanuallayout.ui | 117 ++- src/app/puzzle/layout/vppiece.cpp | 48 - src/app/puzzle/layout/vppiece.h | 12 - src/app/puzzle/puzzle.pro | 9 + src/app/puzzle/scene/vpgraphicspiece.cpp | 2 +- src/app/puzzle/vpmainwindow.cpp | 19 +- .../valentina/dialogs/dialogsavelayout.cpp | 77 +- src/app/valentina/dialogs/dialogsavelayout.ui | 12 +- src/app/valentina/mainwindowsnogui.cpp | 19 +- src/app/valentina/valentina.pro | 9 + src/libs/libs.pro | 3 +- src/libs/libs.qbs | 1 + src/libs/vdxf/vdxfengine.cpp | 2 + src/libs/vformat/vformat.qbs | 4 +- src/libs/vgeometry/vgobject.cpp | 7 +- src/libs/vhpgl/stable.cpp | 30 + src/libs/vhpgl/stable.h | 88 ++ src/libs/vhpgl/vhpgl.pri | 13 + src/libs/vhpgl/vhpgl.pro | 82 ++ src/libs/vhpgl/vhpgl.qbs | 19 + src/libs/vhpgl/vhpglengine.cpp | 941 ++++++++++++++++++ src/libs/vhpgl/vhpglengine.h | 262 +++++ src/libs/vhpgl/vhpglpaintdevice.cpp | 201 ++++ src/libs/vhpgl/vhpglpaintdevice.h | 79 ++ src/libs/vhpgl/warnings.pri | 83 ++ src/libs/vlayout/vlayout.qbs | 1 + src/libs/vlayout/vlayoutdef.h | 2 + src/libs/vlayout/vlayoutexporter.cpp | 79 +- src/libs/vlayout/vlayoutexporter.h | 62 ++ src/libs/vlayout/vlayoutpiece.cpp | 18 +- src/libs/vlayout/vlayoutpiece.h | 71 +- 35 files changed, 2215 insertions(+), 240 deletions(-) create mode 100644 src/libs/vhpgl/stable.cpp create mode 100644 src/libs/vhpgl/stable.h create mode 100644 src/libs/vhpgl/vhpgl.pri create mode 100644 src/libs/vhpgl/vhpgl.pro create mode 100644 src/libs/vhpgl/vhpgl.qbs create mode 100644 src/libs/vhpgl/vhpglengine.cpp create mode 100644 src/libs/vhpgl/vhpglengine.h create mode 100644 src/libs/vhpgl/vhpglpaintdevice.cpp create mode 100644 src/libs/vhpgl/vhpglpaintdevice.h create mode 100644 src/libs/vhpgl/warnings.pri diff --git a/ChangeLog.txt b/ChangeLog.txt index e89093e1f..68fc76498 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -30,6 +30,7 @@ - Independent translation for piece labels. - Piece labels line break. - Support for single-line fonts. +- Export to HP-GL format. # Valentina 0.7.52 September 12, 2022 - Fix crash when default locale is ru. diff --git a/dist/OBS_debian/debian.valentina.1 b/dist/OBS_debian/debian.valentina.1 index af5873f9a..da77d4adf 100644 --- a/dist/OBS_debian/debian.valentina.1 +++ b/dist/OBS_debian/debian.valentina.1 @@ -1,6 +1,6 @@ .\" Manpage for valentina. .\" Contact dismine@gmail.com to correct errors. -.TH valentina 1 "10 April, 2023" "valentina man page" +.TH valentina 1 "July 10, 2023" "valentina man page" .SH NAME Valentina \- Pattern making program. .SH SYNOPSIS @@ -84,7 +84,16 @@ The path to output destination folder. By default the directory at which the app .BR "*" " PDF tiled files (*.pdf) = 33," .RE .RS -.BR "*" " TIFF файли (*.tif) = 35." +.BR "*" " Raw Layout Data files (*.rld) = 35," +.RE +.RS +.BR "*" " TIFF files (*.tif) = 36," +.RE +.RS +.BR "*" " HP-GL files (*.hpgl) = 37," +.RE +.RS +.BR "*" " HP-GL/2 files (*.hpgl) = 38." .RE .IP "--bdxf" .RB "Export dxf in binary form." diff --git a/dist/debian/valentina.1 b/dist/debian/valentina.1 index af5873f9a..da77d4adf 100755 --- a/dist/debian/valentina.1 +++ b/dist/debian/valentina.1 @@ -1,6 +1,6 @@ .\" Manpage for valentina. .\" Contact dismine@gmail.com to correct errors. -.TH valentina 1 "10 April, 2023" "valentina man page" +.TH valentina 1 "July 10, 2023" "valentina man page" .SH NAME Valentina \- Pattern making program. .SH SYNOPSIS @@ -84,7 +84,16 @@ The path to output destination folder. By default the directory at which the app .BR "*" " PDF tiled files (*.pdf) = 33," .RE .RS -.BR "*" " TIFF файли (*.tif) = 35." +.BR "*" " Raw Layout Data files (*.rld) = 35," +.RE +.RS +.BR "*" " TIFF files (*.tif) = 36," +.RE +.RS +.BR "*" " HP-GL files (*.hpgl) = 37," +.RE +.RS +.BR "*" " HP-GL/2 files (*.hpgl) = 38." .RE .IP "--bdxf" .RB "Export dxf in binary form." diff --git a/src/app/puzzle/dialogs/dialogsavemanuallayout.cpp b/src/app/puzzle/dialogs/dialogsavemanuallayout.cpp index e218ec0c7..47908cfc8 100644 --- a/src/app/puzzle/dialogs/dialogsavemanuallayout.cpp +++ b/src/app/puzzle/dialogs/dialogsavemanuallayout.cpp @@ -259,6 +259,8 @@ void DialogSaveManualLayout::SetShowGrainline(bool show) case LayoutExportFormats::DXF_AC1021_Flat: case LayoutExportFormats::DXF_AC1024_Flat: case LayoutExportFormats::DXF_AC1027_Flat: + case LayoutExportFormats::HPGL: + case LayoutExportFormats::HPGL2: ui->checkBoxShowGrainline->setChecked(show); break; default: @@ -288,6 +290,8 @@ auto DialogSaveManualLayout::IsShowGrainline() const -> bool case LayoutExportFormats::DXF_AC1021_Flat: case LayoutExportFormats::DXF_AC1024_Flat: case LayoutExportFormats::DXF_AC1027_Flat: + case LayoutExportFormats::HPGL: + case LayoutExportFormats::HPGL2: return ui->checkBoxShowGrainline->isChecked(); default: return true; @@ -495,35 +499,43 @@ void DialogSaveManualLayout::ShowExample() VCommonSettings *settings = VAbstractApplication::VApp()->Settings(); - ui->checkBoxBinaryDXF->setEnabled(false); - ui->checkBoxTextAsPaths->setEnabled(!settings->GetSingleLineFonts() && !settings->GetSingleStrokeOutlineFont()); - ui->checkBoxExportUnified->setEnabled(false); - ui->checkBoxTilesScheme->setEnabled(false); - ui->checkBoxShowGrainline->setEnabled(true); + ui->labelOptionsNotAvailable->setVisible(false); + ui->checkBoxBinaryDXF->setVisible(false); + ui->checkBoxTextAsPaths->setVisible(false); + ui->checkBoxExportUnified->setVisible(false); + ui->checkBoxTilesScheme->setVisible(false); + ui->checkBoxShowGrainline->setVisible(false); + + const bool editableTextAsPaths = !settings->GetSingleLineFonts() && !settings->GetSingleStrokeOutlineFont(); switch (currentFormat) { case LayoutExportFormats::DXF_AAMA: case LayoutExportFormats::DXF_ASTM: - ui->checkBoxBinaryDXF->setEnabled(true); - ui->checkBoxShowGrainline->setEnabled(false); - break; - case LayoutExportFormats::RLD: - ui->checkBoxTextAsPaths->setEnabled(false); - ui->checkBoxShowGrainline->setEnabled(false); + ui->checkBoxBinaryDXF->setVisible(true); break; case LayoutExportFormats::PDFTiled: - ui->checkBoxTilesScheme->setEnabled(true); - ui->checkBoxExportUnified->setEnabled(true); + ui->checkBoxTextAsPaths->setVisible(editableTextAsPaths); + ui->checkBoxTilesScheme->setVisible(true); + ui->checkBoxExportUnified->setVisible(m_count > 1); + ui->checkBoxShowGrainline->setVisible(true); break; case LayoutExportFormats::PDF: case LayoutExportFormats::PS: case LayoutExportFormats::EPS: - ui->checkBoxExportUnified->setEnabled(true); + ui->checkBoxTextAsPaths->setVisible(editableTextAsPaths); + ui->checkBoxExportUnified->setVisible(m_count > 1); + ui->checkBoxShowGrainline->setVisible(true); break; - case LayoutExportFormats::NC: - case LayoutExportFormats::OBJ: - ui->checkBoxShowGrainline->setEnabled(false); + case LayoutExportFormats::HPGL: + case LayoutExportFormats::HPGL2: + ui->checkBoxShowGrainline->setVisible(true); + break; + case LayoutExportFormats::SVG: + case LayoutExportFormats::PNG: + case LayoutExportFormats::TIF: + ui->checkBoxTextAsPaths->setVisible(editableTextAsPaths); + ui->checkBoxShowGrainline->setVisible(true); break; case LayoutExportFormats::DXF_AC1006_Flat: case LayoutExportFormats::DXF_AC1009_Flat: @@ -534,10 +546,12 @@ void DialogSaveManualLayout::ShowExample() case LayoutExportFormats::DXF_AC1021_Flat: case LayoutExportFormats::DXF_AC1024_Flat: case LayoutExportFormats::DXF_AC1027_Flat: - case LayoutExportFormats::SVG: - case LayoutExportFormats::PNG: - case LayoutExportFormats::TIF: + ui->checkBoxBinaryDXF->setVisible(true); + ui->checkBoxTextAsPaths->setVisible(editableTextAsPaths); + ui->checkBoxShowGrainline->setVisible(true); + break; default: + ui->labelOptionsNotAvailable->setVisible(true); break; } } @@ -587,6 +601,8 @@ auto DialogSaveManualLayout::InitFormats() -> QVector 0 0 - 413 - 293 + 390 + 283 @@ -17,7 +17,7 @@ :/puzzleicon/64x64/logo.png:/puzzleicon/64x64/logo.png - + @@ -111,59 +111,74 @@ Options - - - - - false - + + + - Binary form + Not available - - - - false - - - Export unified - - - true - - + + + + + + true + + + Binary form + + + + + + + true + + + Export unified + + + true + + + + + + + Show grainline + + + true + + + + - - - - Show grainline - - - true - - - - - - - true - - - Text as paths - - - - - - - false - - - Tiles scheme - - + + + + + + true + + + Text as paths + + + + + + + true + + + Tiles scheme + + + + diff --git a/src/app/puzzle/layout/vppiece.cpp b/src/app/puzzle/layout/vppiece.cpp index eeb6d7df2..13ff4c1d9 100644 --- a/src/app/puzzle/layout/vppiece.cpp +++ b/src/app/puzzle/layout/vppiece.cpp @@ -280,54 +280,6 @@ void VPPiece::SetGrainline(const VPieceGrainline &grainline) VLayoutPiece::SetGrainline(grainline); } -//--------------------------------------------------------------------------------------------------------------------- -auto VPPiece::GetPieceLabelRect() const -> QVector -{ - return VLayoutPiece::GetPieceLabelRect(); -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPPiece::SetPieceLabelRect(const QVector &rect) -{ - VLayoutPiece::SetPieceLabelRect(rect); -} - -//--------------------------------------------------------------------------------------------------------------------- -auto VPPiece::GetPieceLabelData() const -> VTextManager -{ - return VLayoutPiece::GetPieceLabelData(); -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPPiece::SetPieceLabelData(const VTextManager &data) -{ - VLayoutPiece::SetPieceLabelData(data); -} - -//--------------------------------------------------------------------------------------------------------------------- -auto VPPiece::GetPatternLabelRect() const -> QVector -{ - return VLayoutPiece::GetPatternLabelRect(); -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPPiece::SetPatternLabelRect(const QVector &rect) -{ - VLayoutPiece::SetPatternLabelRect(rect); -} - -//--------------------------------------------------------------------------------------------------------------------- -auto VPPiece::GetPatternLabelData() const -> VTextManager -{ - return VLayoutPiece::GetPatternLabelData(); -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPPiece::SetPatternLabelData(const VTextManager &data) -{ - VLayoutPiece::SetPatternLabelData(data); -} - //--------------------------------------------------------------------------------------------------------------------- void VPPiece::Flip() { diff --git a/src/app/puzzle/layout/vppiece.h b/src/app/puzzle/layout/vppiece.h index 7e211acb6..6dbe81901 100644 --- a/src/app/puzzle/layout/vppiece.h +++ b/src/app/puzzle/layout/vppiece.h @@ -96,18 +96,6 @@ public: void SetGrainline(const VPieceGrainline &grainline); - auto GetPieceLabelRect() const -> QVector; - void SetPieceLabelRect(const QVector &rect); - - auto GetPieceLabelData() const ->VTextManager; - void SetPieceLabelData(const VTextManager &data); - - auto GetPatternLabelRect() const -> QVector; - void SetPatternLabelRect(const QVector &rect); - - auto GetPatternLabelData() const ->VTextManager; - void SetPatternLabelData(const VTextManager &data); - /** * @brief Flip horizontally mirror around center of bounding rect */ diff --git a/src/app/puzzle/puzzle.pro b/src/app/puzzle/puzzle.pro index 653876c8e..f1994a14a 100644 --- a/src/app/puzzle/puzzle.pro +++ b/src/app/puzzle/puzzle.pro @@ -282,6 +282,15 @@ DEPENDPATH += $$PWD/../../libs/vdxf win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vdxf/$${DESTDIR}/vdxf.lib else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vdxf/$${DESTDIR}/libvdxf.a +# VHPGL static library +unix|win32: LIBS += -L$$OUT_PWD/../../libs/vhpgl/$${DESTDIR}/ -lvhpgl + +INCLUDEPATH += $$PWD/../../libs/vhpgl +DEPENDPATH += $$PWD/../../libs/vhpgl + +win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vhpgl/$${DESTDIR}/vhpgl.lib +else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vhpgl/$${DESTDIR}/libvhpgl.a + # VGAnalytics static library unix|win32: LIBS += -L$$OUT_PWD/../../libs/vganalytics/$${DESTDIR}/ -lvganalytics diff --git a/src/app/puzzle/scene/vpgraphicspiece.cpp b/src/app/puzzle/scene/vpgraphicspiece.cpp index 4a928c66b..82d5a2083 100644 --- a/src/app/puzzle/scene/vpgraphicspiece.cpp +++ b/src/app/puzzle/scene/vpgraphicspiece.cpp @@ -433,7 +433,7 @@ void VPGraphicsPiece::InitPieceLabelSVGFont(const QVector &labelShape, VSvgFont svgFont = engine.Font(); if (!svgFont.IsValid()) { - QString errorMsg = tr("Invalid SVG font '%1'. Fallback to outline font.").arg(svgFont.Name()); + QString errorMsg = QStringLiteral("Invalid SVG font '%1'. Fallback to outline font.").arg(svgFont.Name()); qDebug() << errorMsg; InitPieceLabelOutlineFont(labelShape, tm); return; diff --git a/src/app/puzzle/vpmainwindow.cpp b/src/app/puzzle/vpmainwindow.cpp index c65f7297c..dccce8f94 100644 --- a/src/app/puzzle/vpmainwindow.cpp +++ b/src/app/puzzle/vpmainwindow.cpp @@ -2173,7 +2173,8 @@ void VPMainWindow::RotatePiecesToGrainline() void VPMainWindow::ExportData(const VPExportData &data) { if (data.format == LayoutExportFormats::DXF_AAMA || data.format == LayoutExportFormats::DXF_ASTM || - data.format == LayoutExportFormats::RLD) + data.format == LayoutExportFormats::RLD || data.format == LayoutExportFormats::HPGL || + data.format == LayoutExportFormats::HPGL2) { for (int i = 0; i < data.sheets.size(); ++i) { @@ -2211,7 +2212,8 @@ void VPMainWindow::ExportApparelLayout(const VPExportData &data, const QVectorPuzzleSettings()->SetPathManualLayouts(path); + VPSettings *settings = VPApplication::VApp()->PuzzleSettings(); + settings->SetPathManualLayouts(path); QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wnoexcept") @@ -2225,6 +2227,7 @@ void VPMainWindow::ExportApparelLayout(const VPExportData &data, const QVectorGetSingleLineFonts()); + exporter.SetSingleStrokeOutlineFont(settings->GetSingleStrokeOutlineFont()); + exporter.SetPenWidth(settings->GetLayoutLineWidth()); + exporter.ExportToHPGL(details); + break; + case LayoutExportFormats::HPGL2: + exporter.SetSingleLineFont(settings->GetSingleLineFonts()); + exporter.SetSingleStrokeOutlineFont(settings->GetSingleStrokeOutlineFont()); + exporter.SetPenWidth(settings->GetLayoutLineWidth()); + exporter.ExportToHPGL2(details); + break; default: qDebug() << "Can't recognize file type." << Q_FUNC_INFO; break; diff --git a/src/app/valentina/dialogs/dialogsavelayout.cpp b/src/app/valentina/dialogs/dialogsavelayout.cpp index 8f04ef87d..10aa963c0 100644 --- a/src/app/valentina/dialogs/dialogsavelayout.cpp +++ b/src/app/valentina/dialogs/dialogsavelayout.cpp @@ -209,16 +209,6 @@ void DialogSaveLayout::SetBinaryDXFFormat(bool binary) case LayoutExportFormats::DXF_ASTM: ui->checkBoxBinaryDXF->setChecked(binary); break; - case LayoutExportFormats::SVG: - case LayoutExportFormats::PDF: - case LayoutExportFormats::PDFTiled: - case LayoutExportFormats::PNG: - case LayoutExportFormats::OBJ: - case LayoutExportFormats::PS: - case LayoutExportFormats::EPS: - case LayoutExportFormats::NC: - case LayoutExportFormats::RLD: - case LayoutExportFormats::TIF: default: ui->checkBoxBinaryDXF->setChecked(false); break; @@ -242,16 +232,6 @@ auto DialogSaveLayout::IsBinaryDXFFormat() const -> bool case LayoutExportFormats::DXF_AAMA: case LayoutExportFormats::DXF_ASTM: return ui->checkBoxBinaryDXF->isChecked(); - case LayoutExportFormats::SVG: - case LayoutExportFormats::PDF: - case LayoutExportFormats::PDFTiled: - case LayoutExportFormats::PNG: - case LayoutExportFormats::OBJ: - case LayoutExportFormats::PS: - case LayoutExportFormats::EPS: - case LayoutExportFormats::NC: - case LayoutExportFormats::RLD: - case LayoutExportFormats::TIF: default: return false; } @@ -278,13 +258,10 @@ void DialogSaveLayout::SetShowGrainline(bool show) case LayoutExportFormats::PS: case LayoutExportFormats::EPS: case LayoutExportFormats::TIF: + case LayoutExportFormats::HPGL: + case LayoutExportFormats::HPGL2: ui->checkBoxShowGrainline->setChecked(show); break; - case LayoutExportFormats::DXF_AAMA: - case LayoutExportFormats::DXF_ASTM: - case LayoutExportFormats::RLD: - case LayoutExportFormats::NC: - case LayoutExportFormats::OBJ: default: ui->checkBoxShowGrainline->setChecked(true); break; @@ -312,12 +289,9 @@ auto DialogSaveLayout::IsShowGrainline() const -> bool case LayoutExportFormats::PS: case LayoutExportFormats::EPS: case LayoutExportFormats::TIF: + case LayoutExportFormats::HPGL: + case LayoutExportFormats::HPGL2: return ui->checkBoxShowGrainline->isChecked(); - case LayoutExportFormats::DXF_AAMA: - case LayoutExportFormats::DXF_ASTM: - case LayoutExportFormats::RLD: - case LayoutExportFormats::NC: - case LayoutExportFormats::OBJ: default: return true; } @@ -459,30 +433,38 @@ void DialogSaveLayout::ShowExample() ui->labelExample->setText(tr("Example:") + FileName() + QLatin1Char('1') + VLayoutExporter::ExportFormatSuffix(currentFormat)); - ui->checkBoxBinaryDXF->setEnabled(false); ui->groupBoxPaperFormat->setEnabled(false); ui->groupBoxMargins->setEnabled(false); - ui->checkBoxTextAsPaths->setEnabled(true); - ui->checkBoxShowGrainline->setEnabled(m_mode == Draw::Layout); + + ui->labelOptionsNotAvailable->setVisible(false); + ui->checkBoxBinaryDXF->setVisible(false); + ui->checkBoxTextAsPaths->setVisible(false); + ui->checkBoxShowGrainline->setVisible(false); switch (currentFormat) { case LayoutExportFormats::DXF_AAMA: case LayoutExportFormats::DXF_ASTM: - ui->checkBoxBinaryDXF->setEnabled(true); - ui->checkBoxShowGrainline->setEnabled(false); + ui->checkBoxBinaryDXF->setVisible(true); break; case LayoutExportFormats::PDFTiled: ui->groupBoxPaperFormat->setEnabled(true); ui->groupBoxMargins->setEnabled(true); + ui->checkBoxTextAsPaths->setVisible(m_mode != Draw::Layout); + ui->checkBoxShowGrainline->setVisible(true); break; - case LayoutExportFormats::RLD: - ui->checkBoxTextAsPaths->setEnabled(false); - ui->checkBoxShowGrainline->setEnabled(false); + case LayoutExportFormats::HPGL: + case LayoutExportFormats::HPGL2: + ui->checkBoxShowGrainline->setVisible(true); break; - case LayoutExportFormats::NC: - case LayoutExportFormats::OBJ: - ui->checkBoxShowGrainline->setEnabled(false); + case LayoutExportFormats::SVG: + case LayoutExportFormats::PDF: + case LayoutExportFormats::PNG: + case LayoutExportFormats::PS: + case LayoutExportFormats::EPS: + case LayoutExportFormats::TIF: + ui->checkBoxTextAsPaths->setVisible(m_mode != Draw::Layout); + ui->checkBoxShowGrainline->setVisible(true); break; case LayoutExportFormats::DXF_AC1006_Flat: case LayoutExportFormats::DXF_AC1009_Flat: @@ -493,13 +475,12 @@ void DialogSaveLayout::ShowExample() case LayoutExportFormats::DXF_AC1021_Flat: case LayoutExportFormats::DXF_AC1024_Flat: case LayoutExportFormats::DXF_AC1027_Flat: - case LayoutExportFormats::SVG: - case LayoutExportFormats::PDF: - case LayoutExportFormats::PNG: - case LayoutExportFormats::PS: - case LayoutExportFormats::EPS: - case LayoutExportFormats::TIF: + ui->checkBoxBinaryDXF->setVisible(true); + ui->checkBoxTextAsPaths->setVisible(m_mode != Draw::Layout); + ui->checkBoxShowGrainline->setVisible(true); + break; default: + ui->labelOptionsNotAvailable->setVisible(true); break; } } @@ -714,6 +695,8 @@ auto DialogSaveLayout::InitFormats() -> QVector - false + true Binary form @@ -142,6 +142,16 @@ + + + + Not available + + + Qt::AlignCenter + + + diff --git a/src/app/valentina/mainwindowsnogui.cpp b/src/app/valentina/mainwindowsnogui.cpp index b14f5d772..f9711b6b6 100644 --- a/src/app/valentina/mainwindowsnogui.cpp +++ b/src/app/valentina/mainwindowsnogui.cpp @@ -487,7 +487,8 @@ void MainWindowsNoGUI::ExportData(const QVector &listDetails) const LayoutExportFormats format = m_dialogSaveLayout->Format(); if (format == LayoutExportFormats::DXF_AAMA || format == LayoutExportFormats::DXF_ASTM || - format == LayoutExportFormats::RLD) + format == LayoutExportFormats::RLD || format == LayoutExportFormats::HPGL || + format == LayoutExportFormats::HPGL2) { if (m_dialogSaveLayout->Mode() == Draw::Layout) { @@ -640,7 +641,8 @@ void MainWindowsNoGUI::ExportApparelLayout(const QVector &details, return; } - VAbstractValApplication::VApp()->ValentinaSettings()->SetPathLayout(path); + VValentinaSettings *settings = VAbstractValApplication::VApp()->ValentinaSettings(); + settings->SetPathLayout(path); const LayoutExportFormats format = m_dialogSaveLayout->Format(); QT_WARNING_PUSH @@ -655,6 +657,7 @@ void MainWindowsNoGUI::ExportApparelLayout(const QVector &details, exporter.SetXScale(m_dialogSaveLayout->GetXScale()); exporter.SetYScale(m_dialogSaveLayout->GetYScale()); exporter.SetBinaryDxfFormat(m_dialogSaveLayout->IsBinaryDXFFormat()); + exporter.SetShowGrainline(m_dialogSaveLayout->IsShowGrainline()); switch (format) { @@ -669,6 +672,18 @@ void MainWindowsNoGUI::ExportApparelLayout(const QVector &details, case LayoutExportFormats::RLD: exporter.ExportToRLD(details); break; + case LayoutExportFormats::HPGL: + exporter.SetSingleLineFont(settings->GetSingleLineFonts()); + exporter.SetSingleStrokeOutlineFont(settings->GetSingleStrokeOutlineFont()); + exporter.SetPenWidth(qCeil(settings->WidthHairLine())); + exporter.ExportToHPGL(details); + break; + case LayoutExportFormats::HPGL2: + exporter.SetSingleLineFont(settings->GetSingleLineFonts()); + exporter.SetSingleStrokeOutlineFont(settings->GetSingleStrokeOutlineFont()); + exporter.SetPenWidth(qCeil(settings->WidthHairLine())); + exporter.ExportToHPGL2(details); + break; default: qDebug() << "Can't recognize file type." << Q_FUNC_INFO; break; diff --git a/src/app/valentina/valentina.pro b/src/app/valentina/valentina.pro index 9a435e6ac..5289d8dac 100644 --- a/src/app/valentina/valentina.pro +++ b/src/app/valentina/valentina.pro @@ -698,6 +698,15 @@ DEPENDPATH += $$PWD/../../libs/vdxf win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vdxf/$${DESTDIR}/vdxf.lib else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vdxf/$${DESTDIR}/libvdxf.a +# VHPGL static library +unix|win32: LIBS += -L$$OUT_PWD/../../libs/vhpgl/$${DESTDIR}/ -lvhpgl + +INCLUDEPATH += $$PWD/../../libs/vhpgl +DEPENDPATH += $$PWD/../../libs/vhpgl + +win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vhpgl/$${DESTDIR}/vhpgl.lib +else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vhpgl/$${DESTDIR}/libvhpgl.a + # VGAnalytics static library unix|win32: LIBS += -L$$OUT_PWD/../../libs/vganalytics/$${DESTDIR}/ -lvganalytics diff --git a/src/libs/libs.pro b/src/libs/libs.pro index aad3bde72..0b2ff5861 100644 --- a/src/libs/libs.pro +++ b/src/libs/libs.pro @@ -14,4 +14,5 @@ SUBDIRS = \ vformat \ fervor \ vtest \ - vganalytics + vganalytics \ + vhpgl diff --git a/src/libs/libs.qbs b/src/libs/libs.qbs index a15fba06a..0ef6f741d 100644 --- a/src/libs/libs.qbs +++ b/src/libs/libs.qbs @@ -15,5 +15,6 @@ Project { "vtools/vtools.qbs", "vwidgets/vwidgets.qbs", "vganalytics/vganalytics.qbs", + "vhpgl/vhpgl.qbs", ] } diff --git a/src/libs/vdxf/vdxfengine.cpp b/src/libs/vdxf/vdxfengine.cpp index 2c9cd0f70..8ac2e8451 100644 --- a/src/libs/vdxf/vdxfengine.cpp +++ b/src/libs/vdxf/vdxfengine.cpp @@ -636,6 +636,7 @@ auto VDxfEngine::GetXScale() const -> qreal //--------------------------------------------------------------------------------------------------------------------- void VDxfEngine::SetXScale(const qreal &xscale) { + Q_ASSERT(not isActive()); m_xscale = xscale; } @@ -648,6 +649,7 @@ auto VDxfEngine::GetYScale() const -> qreal //--------------------------------------------------------------------------------------------------------------------- void VDxfEngine::SetYScale(const qreal &yscale) { + Q_ASSERT(not isActive()); m_yscale = yscale; } diff --git a/src/libs/vformat/vformat.qbs b/src/libs/vformat/vformat.qbs index 23fed0995..ddfb3315e 100644 --- a/src/libs/vformat/vformat.qbs +++ b/src/libs/vformat/vformat.qbs @@ -1,5 +1,5 @@ VLib { - Depends { name: "Qt"; submodules: ["xml"] } + Depends { name: "Qt"; submodules: ["gui", "xml"] } Depends { name: "IFCLib" } name: "VFormatLib" @@ -20,7 +20,7 @@ VLib { Export { Depends { name: "cpp" } - Depends { name: "Qt"; submodules: ["xml"] } + Depends { name: "Qt"; submodules: ["gui", "xml"] } cpp.includePaths: [exportingProduct.sourceDirectory] } } diff --git a/src/libs/vgeometry/vgobject.cpp b/src/libs/vgeometry/vgobject.cpp index 2427a2605..45bc257d3 100644 --- a/src/libs/vgeometry/vgobject.cpp +++ b/src/libs/vgeometry/vgobject.cpp @@ -40,7 +40,7 @@ #include "../vmisc/compatibility.h" #include "../vmisc/def.h" #include "../vmisc/vabstractapplication.h" -#include "vgeometry/vgeometrydef.h" +#include "vgeometrydef.h" #include "vgobject_p.h" namespace @@ -651,6 +651,11 @@ auto VGObject::CorrectDistortion(const QPointF &t, const QPointF &p1, const QPoi */ auto VGObject::IsPointOnLineviaPDP(const QPointF &t, const QPointF &p1, const QPointF &p2, qreal accuracy) -> bool { + if (p1 == p2) + { + return VFuzzyComparePoints(p1, t, accuracy); + } + const double p = qAbs(PerpDotProduct(p1, p2, t)); const double e = GetEpsilon(t, p1, p2, accuracy); diff --git a/src/libs/vhpgl/stable.cpp b/src/libs/vhpgl/stable.cpp new file mode 100644 index 000000000..c87b09b7c --- /dev/null +++ b/src/libs/vhpgl/stable.cpp @@ -0,0 +1,30 @@ +/************************************************************************ + ** + ** @file stable.cpp + ** @author Roman Telezhynskyi + ** @date 10 12, 2014 + ** + ** @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) 2013-2015 Valentina project + ** 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 . + ** + *************************************************************************/ + +// Build the precompiled headers. +#include "stable.h" diff --git a/src/libs/vhpgl/stable.h b/src/libs/vhpgl/stable.h new file mode 100644 index 000000000..4585cd661 --- /dev/null +++ b/src/libs/vhpgl/stable.h @@ -0,0 +1,88 @@ +/************************************************************************ + ** + ** @file stable.h + ** @author Roman Telezhynskyi + ** @date 10 12, 2014 + ** + ** @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) 2013-2015 Valentina project + ** 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 . + ** + *************************************************************************/ + +#ifndef STABLE_H +#define STABLE_H + +/* I like to include this pragma too, so the build log indicates if pre-compiled headers were in use. */ +#pragma message("Compiling precompiled headers for VWidgets library.\n") + +/* Add C includes here */ + +#if defined __cplusplus +/* Add C++ includes here */ + +#ifdef QT_CORE_LIB +# include +#endif + +#ifdef QT_GUI_LIB +# include +#endif + +#ifdef QT_XML_LIB +# include +#endif + +#ifdef QT_WINEXTRAS_LIB +# include +#endif + +#ifdef QT_WIDGETS_LIB +# include +#endif + +#ifdef QT_SVG_LIB +# include +#endif + +#ifdef QT_PRINTSUPPORT_LIB +# include +#endif + +#ifdef QT_XMLPATTERNS_LIB +# include +#endif + +#ifdef QT_NETWORK_LIB +# include +#endif + +#ifdef QT_CONCURRENT_LIB +# include +#endif + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#ifdef QT_OPENGLWIDGETS_LIB +# include +#endif +#endif + +#endif/*__cplusplus*/ + +#endif // STABLE_H diff --git a/src/libs/vhpgl/vhpgl.pri b/src/libs/vhpgl/vhpgl.pri new file mode 100644 index 000000000..ed45f121c --- /dev/null +++ b/src/libs/vhpgl/vhpgl.pri @@ -0,0 +1,13 @@ +# ADD TO EACH PATH $$PWD VARIABLE!!!!!! +# This need for corect working file translations.pro + +SOURCES += \ + $$PWD/vhpglengine.cpp \ + $$PWD/vhpglpaintdevice.cpp + +*msvc*:SOURCES += $$PWD/stable.cpp + +HEADERS += \ + $$PWD/stable.h \ + $$PWD/vhpglengine.h \ + $$PWD/vhpglpaintdevice.h diff --git a/src/libs/vhpgl/vhpgl.pro b/src/libs/vhpgl/vhpgl.pro new file mode 100644 index 000000000..11fea2b4d --- /dev/null +++ b/src/libs/vhpgl/vhpgl.pro @@ -0,0 +1,82 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2015-06-15T15:24:19 +# +#------------------------------------------------- + +# File with common stuff for whole project +include(../../../common.pri) + +# Name of the library +TARGET = vhpgl + +# We want create a library +TEMPLATE = lib + +CONFIG += staticlib # Making static library + +# Since Q5.12 available support for C++17 +equals(QT_MAJOR_VERSION, 5):greaterThan(QT_MINOR_VERSION, 11) { + CONFIG += c++17 +} else { + CONFIG += c++14 +} + +# Use out-of-source builds (shadow builds) +CONFIG -= debug_and_release debug_and_release_target + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +# Since Qt 5.4.0 the source code location is recorded only in debug builds. +# We need this information also in release builds. For this need define QT_MESSAGELOGCONTEXT. +DEFINES += QT_MESSAGELOGCONTEXT + +include(vhpgl.pri) + +# This is static library so no need in "make install" + +# directory for executable file +DESTDIR = bin + +# files created moc +MOC_DIR = moc + +# objecs files +OBJECTS_DIR = obj + +# Set using ccache. Function enable_ccache() defined in common.pri. +$$enable_ccache() + +include(warnings.pri) + +CONFIG(release, debug|release){ + # Release mode + !*msvc*:CONFIG += silent + + !unix:*g++*{ + QMAKE_CXXFLAGS += -fno-omit-frame-pointer # Need for exchndl.dll + } + + noDebugSymbols{ # For enable run qmake with CONFIG+=noDebugSymbols + # do nothing + } else { + !macx:!*msvc*{ + # Turn on debug symbols in release mode on Unix systems. + # On Mac OS X temporarily disabled. TODO: find way how to strip binary file. + QMAKE_CXXFLAGS_RELEASE += -g -gdwarf-3 + QMAKE_CFLAGS_RELEASE += -g -gdwarf-3 + QMAKE_LFLAGS_RELEASE = + } + } +} + +include (../libs.pri) diff --git a/src/libs/vhpgl/vhpgl.qbs b/src/libs/vhpgl/vhpgl.qbs new file mode 100644 index 000000000..c3d709a08 --- /dev/null +++ b/src/libs/vhpgl/vhpgl.qbs @@ -0,0 +1,19 @@ +VLib { + Depends { name: "Qt"; submodules: ["core"] } + Depends { name: "VMiscLib"} + Depends { name: "VFormatLib"} + + name: "VHPGLLib" + + files: [ + "vhpglengine.cpp", + "vhpglengine.h", + "vhpglpaintdevice.cpp", + "vhpglpaintdevice.h", + ] + + Export { + Depends { name: "cpp" } + cpp.includePaths: [exportingProduct.sourceDirectory] + } +} diff --git a/src/libs/vhpgl/vhpglengine.cpp b/src/libs/vhpgl/vhpglengine.cpp new file mode 100644 index 000000000..e462a7b8b --- /dev/null +++ b/src/libs/vhpgl/vhpglengine.cpp @@ -0,0 +1,941 @@ +/************************************************************************ + ** + ** @file vhpglengine.cpp + ** @author Roman Telezhynskyi + ** @date 7 7, 2020 + ** + ** @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 + ** 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 . + ** + *************************************************************************/ +#include "vhpglengine.h" + +#include "../vformat/vsinglelineoutlinechar.h" +#include "../vgeometry/vlayoutplacelabel.h" +#include "../vlayout/vlayoutpiece.h" +#include "../vlayout/vlayoutpiecepath.h" +#include "../vlayout/vlayoutpoint.h" +#include "../vlayout/vtextmanager.h" +#include "../vmisc/def.h" +#include "../vmisc/defglobal.h" +#include "../vmisc/svgfont/vsvgfont.h" +#include "../vmisc/svgfont/vsvgfontdatabase.h" +#include "../vmisc/svgfont/vsvgfontengine.h" +#include "../vmisc/vabstractapplication.h" +#include "qmath.h" + +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) +#include "../vmisc/backport/text.h" +#endif + +#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0) +#include "../vmisc/diagnostic.h" +#endif // QT_VERSION < QT_VERSION_CHECK(5, 5, 0) + +#include +#include +#include + +namespace +{ +const qreal accuracyPointOnLine{0.99}; + +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wunused-member-function") + +// mnemonics +Q_GLOBAL_STATIC_WITH_ARGS(const QString, mIN, (QLatin1String("IN"))) // NOLINT initialize set instruction +Q_GLOBAL_STATIC_WITH_ARGS(const QString, mPU, (QLatin1String("PU"))) // NOLINT pen up +Q_GLOBAL_STATIC_WITH_ARGS(const QString, mPD, (QLatin1String("PD"))) // NOLINT pen down +Q_GLOBAL_STATIC_WITH_ARGS(const QString, mLT, (QLatin1String("LT"))) // NOLINT line type +Q_GLOBAL_STATIC_WITH_ARGS(const QString, mSP, (QLatin1String("SP"))) // NOLINT select pen +Q_GLOBAL_STATIC_WITH_ARGS(const QString, mPG, (QLatin1String("PG"))) // NOLINT page feed +Q_GLOBAL_STATIC_WITH_ARGS(const QString, mPA, (QLatin1String("PA"))) // NOLINT plot absolute +Q_GLOBAL_STATIC_WITH_ARGS(const QString, mPW, (QLatin1String("PW"))) // NOLINT pen width +Q_GLOBAL_STATIC_WITH_ARGS(const QString, mLA, (QLatin1String("LA"))) // NOLINT line attributes + +QT_WARNING_POP + +//--------------------------------------------------------------------------------------------------------------------- +Q_DECL_RELAXED_CONSTEXPR inline auto ConvertPixels(qreal pix) -> qreal +{ + // Default plating measurement in the HP-GL(HP-GL/2) graphics mode is 1/1016"(0.025mm). + // 40 plotter units = 1 mm + return FromPixel(pix, Unit::Mm) * 40.; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto RemoveDublicates(QVector points) -> QVector +{ + if (points.size() < 3) + { + return points; + } + + for (int i = 0; i < points.size() - 1; ++i) + { + if (points.at(i) == points.at(i + 1)) + { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + points.erase(points.cbegin() + i + 1); +#else + points.erase(points.begin() + i + 1); +#endif + --i; + } + } + + return points; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto OptimizePath(QVector path) -> QVector +{ + if (path.size() < 3) + { + return path; + } + + path = RemoveDublicates(path); + + if (path.size() < 3) + { + return path; + } + + vsizetype prev = -1; + const bool closedPath = (path.first() == path.last()); + const vsizetype startIndex = closedPath ? 0 : 1; + const vsizetype endIndex = closedPath ? path.size() : path.size() - 1; + + QVector cleared; + cleared.reserve(path.size()); + + if (!closedPath) + { + cleared.append(path.first()); + } + + // Remove point on line + for (vsizetype i = startIndex; i < endIndex; ++i) + { + if (prev == -1) + { + prev = (i == 0) ? path.size() - 1 : i - 1; + } + + const vsizetype next = (i == path.size() - 1) ? 0 : i + 1; + + const QPoint &iPoint = path.at(i); + const QPoint &prevPoint = path.at(prev); + const QPoint &nextPoint = path.at(next); + + // If RemoveDublicates does not remove these points it is a valid case. + // Case where last point equal first point + if (((i == 0 || i == path.size() - 1) && (iPoint == prevPoint || iPoint == nextPoint)) || + not VGObject::IsPointOnLineviaPDP(iPoint, prevPoint, nextPoint, accuracyPointOnLine)) + { + cleared.append(iPoint); + prev = -1; + } + } + + if (!closedPath) + { + cleared.append(path.last()); + } + + cleared = RemoveDublicates(cleared); + + return cleared; +} + +//--------------------------------------------------------------------------------------------------------------------- +template inline auto CastToPoint(const QVector &points) -> QVector +{ + QVector casted; + casted.reserve(points.size()); + + for (const auto &p : points) + { + casted.append(p.toPoint()); + } + + return casted; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto LineFont(const TextLine &tl, const VSvgFont &base) -> VSvgFont +{ + VSvgFont fnt = base; + fnt.SetPointSize(base.PointSize() + tl.m_iFontSize); + fnt.SetBold(tl.m_bold); + fnt.SetItalic(tl.m_italic); + return fnt; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto LineFont(const TextLine &tl, const QFont &base) -> QFont +{ + QFont fnt = base; + fnt.setPointSize(base.pointSize() + tl.m_iFontSize); + fnt.setBold(tl.m_bold); + fnt.setItalic(tl.m_italic); + return fnt; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto LineAlign(const TextLine &tl, const QString &text, const VSvgFontEngine &engine, qreal width, qreal penWidth) + -> qreal +{ + const int lineWidth = qRound(engine.TextWidth(text, penWidth)); + + qreal dX = 0; + if (tl.m_eAlign == 0 || (tl.m_eAlign & Qt::AlignLeft) > 0) + { + dX = 0; + } + else if ((tl.m_eAlign & Qt::AlignHCenter) > 0) + { + dX = (width - lineWidth) / 2; + } + else if ((tl.m_eAlign & Qt::AlignRight) > 0) + { + dX = width - lineWidth; + } + + return dX; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto LineAlign(const TextLine &tl, const QString &text, const QFontMetrics &fm, qreal width) -> qreal +{ + const int lineWidth = TextWidth(fm, text); + + qreal dX = 0; + if (tl.m_eAlign == 0 || (tl.m_eAlign & Qt::AlignLeft) > 0) + { + dX = 0; + } + else if ((tl.m_eAlign & Qt::AlignHCenter) > 0) + { + dX = (width - lineWidth) / 2; + } + else if ((tl.m_eAlign & Qt::AlignRight) > 0) + { + dX = width - lineWidth; + } + + return dX; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto LineMatrix(const VLayoutPiece &piece, const QPointF &topLeft, qreal angle, const QPointF &linePos, + int maxLineWidth) -> QTransform +{ + QTransform labelMatrix; + labelMatrix.translate(topLeft.x(), topLeft.y()); + + if (piece.IsMirror()) + { + labelMatrix.scale(-1, 1); + labelMatrix.rotate(-angle); + labelMatrix.translate(-maxLineWidth, 0); + } + else + { + labelMatrix.rotate(angle); + } + + labelMatrix.translate(linePos.x(), linePos.y()); // Each string has own position + labelMatrix *= piece.GetMatrix(); + + return labelMatrix; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto OptimizePattern(QVector pattern) -> QVector +{ + // Extend the pattern if it has an odd number of elements + if (pattern.size() % 2 == 1) + { + const vsizetype originalSize = pattern.size(); + pattern.reserve(originalSize * 2); + + for (int i = 0; i < originalSize; ++i) + { + pattern.append(pattern.at(i)); + } + } + + return pattern; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto CurrentPatternDistance(qreal patternDistance, bool dashMode, const QVector &pattern, int patternIndex) + -> qreal +{ + if (qFuzzyIsNull(patternDistance)) + { + patternDistance = dashMode ? qAbs(pattern[patternIndex % pattern.size()]) + : qAbs(pattern[(patternIndex + 1) % pattern.size()]); + } + + return patternDistance; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto NextPattern(int patternIndex, const QVector &pattern) -> int +{ + return (patternIndex + 2) % static_cast(pattern.size()); +} +} // namespace + +//--------------------------------------------------------------------------------------------------------------------- +auto VHPGLEngine::SortDetails(const QVector &details) -> QList +{ + QList sorted; + + for (const auto &detail : details) + { + if (detail.GetPriority() == 0 || sorted.isEmpty()) + { + sorted.append(detail); + } + else + { + bool found = false; + for (int i = 0; i < sorted.size(); ++i) + { + if (detail.GetPriority() < sorted.at(i).GetPriority() || sorted.at(i).GetPriority() == 0) + { + sorted.insert(i, detail); + found = true; + break; + } + } + + if (not found) + { + sorted.append(detail); + } + } + } + + return sorted; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VHPGLEngine::GenerateHPGL(const QVector &details) -> bool +{ + if (details.isEmpty()) + { + qCritical() << "VHPGLEngine::GenerateHPGL(), details list is empty"; + return false; + } + + if (not m_size.isValid()) + { + qCritical() << "VHPGLEngine::GenerateHPGL(), size is not valid"; + return false; + } + + m_currentPos = QPoint(-1, -1); // Fake position + + QFile data(m_fileName); + if (data.open(QFile::WriteOnly | QFile::Truncate)) + { + QTextStream out(&data); + out.setRealNumberPrecision(0); + + GenerateHPGLHeader(out); + ExportDetails(out, SortDetails(details)); + GenerateHPGLFooter(out); + + data.close(); + } + else + { + qCritical() << "VHPGLEngine::GenerateHPGL(), cannot open file " << m_fileName << ". Reason " << data.error() + << "."; + return false; + } + + return true; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VHPGLEngine::GenerateHPGL2(const QVector &details) -> bool +{ + if (details.isEmpty()) + { + qCritical() << "VHPGLEngine::ExportToHPGL2(), details list is empty"; + return false; + } + + if (not m_size.isValid()) + { + qCritical() << "VHPGLEngine::ExportToHPGL2(), size is not valid"; + return false; + } + + m_ver2 = true; + m_currentPos = QPoint(-1, -1); // Fake position + + QFile data(m_fileName); + if (data.open(QFile::WriteOnly | QFile::Truncate)) + { + QTextStream out(&data); + out.setRealNumberPrecision(6); + + GenerateHPGLHeader(out); + ExportDetails(out, SortDetails(details)); + GenerateHPGLFooter(out); + + data.close(); + } + else + { + qCritical() << "VHPGLEngine::ExportToHPGL2(), cannot open file " << m_fileName << ". Reason " << data.error() + << "."; + return false; + } + + return true; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::HPComand(QTextStream &out, const QString &mnemonic, const QString ¶meters) const +{ + out << qPrintable(mnemonic + parameters) << ';'; + if (m_inserNewLine) + { + out << Qt::endl; + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::GenerateHPGLHeader(QTextStream &out) +{ + HPComand(out, *mIN); + HPPenUp(out); + HPComand(out, *mSP, QChar('1')); // select first pen + HPComand(out, *mLT); // select line type by default + HPComand(out, *mPA); + HPPenUp(out, QPoint()); // move to the origin + + if (m_ver2) + { + HPComand(out, *mPW, QString::number(FromPixel(m_penWidthPx, Unit::Mm), 'f', 6)); + HPComand(out, *mLA, QStringLiteral("1,4,2,4")); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::ExportDetails(QTextStream &out, const QList &details) +{ + for (auto detail : details) + { + detail.Scale(m_xscale, m_yscale); + + PlotSeamAllowance(out, detail); + PlotMainPath(out, detail); + PlotInternalPaths(out, detail); + PlotGrainline(out, detail); + PlotPlaceLabels(out, detail); + PlotPassmarks(out, detail); + PlotLabels(out, detail); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::GenerateHPGLFooter(QTextStream &out) +{ + HPPenUp(out); // pen up + HPComand(out, *mSP, QChar('0')); // select pen + HPComand(out, *mPG); // Page Feed +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::PlotMainPath(QTextStream &out, const VLayoutPiece &detail) +{ + if (not detail.IsSeamAllowance() || + (detail.IsSeamAllowance() && not detail.IsSeamAllowanceBuiltIn() && not detail.IsHideMainPath())) + { + QVector points = CastToPoint(ConvertPath(detail.GetMappedContourPoints())); + + if (points.size() > 1 && points.first() != points.last()) + { + points.append(points.first()); // must be closed + } + + PlotPath(out, points, Qt::DashLine); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::PlotSeamAllowance(QTextStream &out, const VLayoutPiece &detail) +{ + QVector points = detail.IsSeamAllowance() && not detail.IsSeamAllowanceBuiltIn() + ? CastToPoint(ConvertPath(detail.GetMappedSeamAllowancePoints())) + : CastToPoint(ConvertPath(detail.GetMappedContourPoints())); + + if (points.size() > 1 && points.first() != points.last()) + { + points.append(points.first()); // must be closed + } + + PlotPath(out, points, Qt::DashDotLine); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::PlotInternalPaths(QTextStream &out, const VLayoutPiece &detail) +{ + QVector internalPaths = detail.GetInternalPaths(); + for (const auto &path : internalPaths) + { + QVector points = VLayoutPiece::Map(path.Points(), detail.GetMatrix(), detail.IsMirror()); + PlotPath(out, CastToPoint(ConvertPath(points)), path.PenStyle()); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::PlotPlaceLabels(QTextStream &out, const VLayoutPiece &detail) +{ + const QVector placeLabels = detail.GetPlaceLabels(); + for (const auto &pLabel : placeLabels) + { + PlaceLabelImg shape = detail.MapPlaceLabelShape(VAbstractPiece::PlaceLabelShape(pLabel)); + for (auto &subShape : shape) + { + PlotPath(out, CastToPoint(ConvertPath(subShape)), Qt::SolidLine); + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::PlotPassmarks(QTextStream &out, const VLayoutPiece &detail) +{ + const QVector passmarks = detail.GetMappedPassmarks(); + for (const auto &passmark : passmarks) + { + for (const auto &subLine : passmark.lines) + { + HPPenUp(out, ConvertPoint(subLine.p1()).toPoint()); + HPPenDown(out, ConvertPoint(subLine.p2()).toPoint()); + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::PlotLabels(QTextStream &out, const VLayoutPiece &detail) +{ + PlotLabel(out, detail, detail.GetPieceLabelRect(), detail.GetPieceLabelData()); + PlotLabel(out, detail, detail.GetPatternLabelRect(), detail.GetPatternLabelData()); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::PlotGrainline(QTextStream &out, const VLayoutPiece &detail) +{ + if (!m_showGrainline) + { + return; + } + + GrainlineShape shape = detail.GetMappedGrainlineShape(); + for (const auto &subShape : shape) + { + PlotPath(out, CastToPoint(ConvertPath(subShape)), Qt::SolidLine); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::PlotLabel(QTextStream &out, const VLayoutPiece &detail, const QVector &labelShape, + const VTextManager &tm) +{ + if (m_singleLineFont) + { + PlotLabelSVGFont(out, detail, labelShape, tm); + } + else + { + PlotLabelOutlineFont(out, detail, labelShape, tm); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::PlotLabelSVGFont(QTextStream &out, const VLayoutPiece &detail, const QVector &labelShape, + const VTextManager &tm) +{ + if (labelShape.count() <= 2) + { + return; + } + + VSvgFontDatabase *db = VAbstractApplication::VApp()->SVGFontDatabase(); + VSvgFontEngine engine = + db->FontEngine(tm.GetSVGFontFamily(), SVGFontStyle::Normal, SVGFontWeight::Normal, tm.GetSVGFontPointSize()); + + VSvgFont svgFont = engine.Font(); + if (!svgFont.IsValid()) + { + qDebug() << QStringLiteral("Invalid SVG font '%1'. Fallback to outline font.").arg(svgFont.Name()); + PlotLabelOutlineFont(out, detail, labelShape, tm); + return; + } + + const qreal dW = QLineF(labelShape.at(0), labelShape.at(1)).length(); + const qreal dH = QLineF(labelShape.at(1), labelShape.at(2)).length(); + const qreal angle = -QLineF(labelShape.at(0), labelShape.at(1)).angle(); + const int maxLineWidth = tm.MaxLineWidthSVGFont(static_cast(dW), m_penWidthPx); + + qreal dY = m_penWidthPx; + + const QVector labelLines = tm.GetLabelSourceLines(qFloor(dW), svgFont, m_penWidthPx); + + for (const auto &tl : labelLines) + { + const VSvgFont fnt = LineFont(tl, svgFont); + engine = db->FontEngine(fnt); + + if (dY + engine.FontHeight() + m_penWidthPx > dH) + { + break; + } + + 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); + + QPainterPath path = lineMatrix.map(engine.DrawPath(QPointF(), qsText)); + PlotPainterPath(out, path, Qt::SolidLine); + + dY += engine.FontHeight() + m_penWidthPx + tm.GetSpacing(); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::PlotLabelOutlineFont(QTextStream &out, const VLayoutPiece &detail, const QVector &labelShape, + const VTextManager &tm) +{ + if (labelShape.count() <= 2) + { + return; + } + + const qreal dW = QLineF(labelShape.at(0), labelShape.at(1)).length(); + const qreal dH = QLineF(labelShape.at(1), labelShape.at(2)).length(); + const qreal angle = -QLineF(labelShape.at(0), labelShape.at(1)).angle(); + const int maxLineWidth = tm.MaxLineWidthOutlineFont(static_cast(dW)); + + qreal dY = 0; + + VCommonSettings *settings = VAbstractApplication::VApp()->Settings(); + + if (m_singleStrokeOutlineFont) + { + dY += m_penWidthPx; + } + + const QVector labelLines = tm.GetLabelSourceLines(qFloor(dW), tm.GetFont()); + + for (const auto &tl : labelLines) + { + const QFont fnt = LineFont(tl, tm.GetFont()); + + VSingleLineOutlineChar corrector(fnt); + if (m_singleStrokeOutlineFont && !corrector.IsPopulated()) + { + corrector.LoadCorrections(settings->GetPathFontCorrections()); + } + + QFontMetrics fm(fnt); + + if (dY + fm.height() > dH) + { + break; + } + + 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); + + QPainterPath path; + + if (m_singleStrokeOutlineFont) + { + int w = 0; + for (auto c : qAsConst(qsText)) + { + path.addPath(corrector.DrawChar(w, static_cast(fm.ascent()), c)); + w += TextWidth(fm, c); + } + } + else + { + path.addText(0, static_cast(fm.ascent()), fnt, qsText); + } + + PlotPainterPath(out, lineMatrix.map(path), Qt::SolidLine); + + dY += fm.height() + m_penWidthPx + tm.GetSpacing(); + } +} + +//--------------------------------------------------------------------------------------------------------------------- + +template auto VHPGLEngine::ConvertPath(const QVector &path) const -> QVector +{ + QVector convertedPath; + convertedPath.reserve(path.size()); + + for (const auto &point : path) + { + convertedPath.append(ConvertPoint(point)); + } + + return convertedPath; +} + +//--------------------------------------------------------------------------------------------------------------------- +template auto VHPGLEngine::ConvertPoint(T point) const -> T +{ + point.setY(point.y() * -1 + m_size.height()); + + return {ConvertPixels(point.x()), ConvertPixels(point.y())}; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::PlotPath(QTextStream &out, QVector path, Qt::PenStyle penStyle) +{ + if (penStyle == Qt::NoPen) + { + return; + } + + path = OptimizePath(path); + + if (penStyle != Qt::SolidLine && penStyle != Qt::DashLine && penStyle != Qt::DotLine && + penStyle != Qt::DashDotLine && penStyle != Qt::DashDotDotLine) + { + penStyle = Qt::SolidLine; + } + + if (penStyle == Qt::SolidLine) + { + PlotSolidLinePath(out, path); + } + else + { + QVector patetrn = PatternForStyle(penStyle); + PlotPathForStyle(out, path, patetrn); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::PlotSolidLinePath(QTextStream &out, QVector path) +{ + if (path.size() < 2) + { + HPPenUp(out, path.first()); + HPPenDown(out); + return; + } + + HPPenUp(out, path.first()); + + for (int i = 1; i < path.size(); ++i) + { + HPPenDown(out, path.at(i)); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::PlotPathForStyle(QTextStream &out, QVector path, QVector pattern) +{ + if (pattern.isEmpty()) + { + return; + } + + if (path.size() < 2) + { + HPPenUp(out, path.first()); + HPPenDown(out); + return; + } + + pattern = OptimizePattern(pattern); + + bool dashMode = true; + int patternIndex = 0; + qreal patternDistance = 0.0; + + HPPenUp(out, path.first()); + + for (int i = 1; i < path.size(); ++i) + { + QPointF prevPoint = path.at(i - 1); + QPoint currPoint = path.at(i); + + qreal distance = QLineF(prevPoint, currPoint).length(); + qreal segmentDistance = 0; + do + { + qreal subDistance = QLineF(prevPoint, currPoint).length(); + patternDistance = CurrentPatternDistance(patternDistance, dashMode, pattern, patternIndex); + + if (subDistance < patternDistance) + { + if (dashMode) + { + HPPenDown(out, currPoint); + } + patternDistance = patternDistance - subDistance; + break; + } + + if (VFuzzyComparePossibleNulls(subDistance, patternDistance)) + { + if (dashMode) + { + HPPenDown(out, currPoint); + dashMode = false; + } + else + { + HPPenUp(out, currPoint); + dashMode = true; + patternIndex = NextPattern(patternIndex, pattern); + } + patternDistance = 0; + break; + } + + QLineF segment(prevPoint, currPoint); + segment.setLength(patternDistance); + prevPoint = segment.p2(); + segmentDistance += patternDistance; + patternDistance = 0; + + if (dashMode) + { + HPPenDown(out, prevPoint.toPoint()); + dashMode = false; + } + else + { + HPPenUp(out, prevPoint.toPoint()); + dashMode = true; + patternIndex = NextPattern(patternIndex, pattern); + } + } while (distance - segmentDistance > 0); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::PlotPainterPath(QTextStream &out, const QPainterPath &path, Qt::PenStyle penStyle) +{ + const QList subpaths = path.toSubpathPolygons(); + + for (const auto &subpath : subpaths) + { + PlotPath(out, CastToPoint(ConvertPath(subpath)), penStyle); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::HPPenUp(QTextStream &out, QPoint point) +{ + if (m_currentPos != point) + { + HPComand(out, *mPU, QStringLiteral("%1,%2").arg(point.x()).arg(point.y())); + m_currentPos = point; + } + else + { + HPPenUp(out); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::HPPenUp(QTextStream &out) +{ + HPComand(out, *mPU); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::HPPenDown(QTextStream &out, QPoint point) +{ + if (m_currentPos != point) + { + HPComand(out, *mPD, QStringLiteral("%1,%2").arg(point.x()).arg(point.y())); + m_currentPos = point; + } + else + { + HPPenDown(out); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::HPPenDown(QTextStream &out) +{ + HPComand(out, *mPD); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VHPGLEngine::PatternForStyle(Qt::PenStyle style) const -> QVector +{ + int penWidth = m_penWidthPx; + + if (penWidth <= 0) + { + penWidth = qCeil(ToPixel(0.025, Unit::Mm)); + } + + const int space = qCeil(ToPixel(2, Unit::Mm)) * penWidth * 3; + const int dot = qCeil(ToPixel(1, Unit::Mm)); + const int dash = qCeil(ToPixel(4, Unit::Mm)); + + QVector pattern; + pattern.reserve(6); + + switch (style) + { + case Qt::DashLine: + pattern << dash << space; + break; + case Qt::DotLine: + pattern << dot << space; + break; + case Qt::DashDotLine: + pattern << dash << space << dot << space; + break; + case Qt::DashDotDotLine: + pattern << dash << space << dot << space << dot << space; + break; + default: + break; + } + return pattern; +} diff --git a/src/libs/vhpgl/vhpglengine.h b/src/libs/vhpgl/vhpglengine.h new file mode 100644 index 000000000..8263dc127 --- /dev/null +++ b/src/libs/vhpgl/vhpglengine.h @@ -0,0 +1,262 @@ +/************************************************************************ + ** + ** @file vhpglengine.h + ** @author Roman Telezhynskyi + ** @date 7 7, 2020 + ** + ** @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 + ** 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 . + ** + *************************************************************************/ +#ifndef VHPGLENGINE_H +#define VHPGLENGINE_H + +#include "../vmisc/def.h" +#include +#include +#include +#include + +#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0) +#include "../vmisc/defglobal.h" +#endif + +class VLayoutPiece; +class VLayoutPoint; +class QTextStream; +class VTextManager; +class QPainterPath; + +class VHPGLEngine +{ + friend class VHPGLPaintDevice; + +public: + VHPGLEngine() = default; + ~VHPGLEngine() = default; + + auto isActive() const -> bool; + void setActive(bool newState); + + auto GetSize() const -> QSize; + void SetSize(QSize size); + + auto GetFileName() const -> QString; + void SetFileName(const QString &filename); + + auto GetSingleLineFont() const -> bool; + void SetSingleLineFont(bool singleLineFont); + + auto GetSingleStrokeOutlineFont() const -> bool; + void SetSingleStrokeOutlineFont(bool singleStrokeOutlineFont); + + auto GetPenWidth() const -> int; + void SetPenWidth(int newPenWidth); + + auto GetXScale() const -> qreal; + void SetXScale(const qreal &xscale); + + auto GetYScale() const -> qreal; + void SetYScale(const qreal &yscale); + + void SetIsertNewLine(bool insert); + + static auto SortDetails(const QVector &details) -> QList; + + auto GetShowGrainline() const -> bool; + void SetShowGrainline(bool newShowGrainline); + +private: + Q_DISABLE_COPY_MOVE(VHPGLEngine) // NOLINT + bool m_ver2{false}; + bool m_active{false}; + QSize m_size{}; + QString m_fileName{}; + bool m_inserNewLine{true}; + QPoint m_currentPos{-1, -1}; + bool m_singleLineFont{false}; + bool m_singleStrokeOutlineFont{false}; + int m_penWidthPx{qCeil(ToPixel(0.025, Unit::Mm))}; + qreal m_xscale{1}; + qreal m_yscale{1}; + bool m_showGrainline{true}; + + auto GenerateHPGL(const QVector &details) -> bool; + auto GenerateHPGL2(const QVector &details) -> bool; + + void HPComand(QTextStream &out, const QString &mnemonic, const QString ¶meters = QString()) const; + void GenerateHPGLHeader(QTextStream &out); + void ExportDetails(QTextStream &out, const QList &details); + void GenerateHPGLFooter(QTextStream &out); + + void PlotMainPath(QTextStream &out, const VLayoutPiece &detail); + void PlotSeamAllowance(QTextStream &out, const VLayoutPiece &detail); + void PlotInternalPaths(QTextStream &out, const VLayoutPiece &detail); + void PlotPlaceLabels(QTextStream &out, const VLayoutPiece &detail); + void PlotPassmarks(QTextStream &out, const VLayoutPiece &detail); + void PlotLabels(QTextStream &out, const VLayoutPiece &detail); + void PlotGrainline(QTextStream &out, const VLayoutPiece &detail); + + void PlotLabel(QTextStream &out, const VLayoutPiece &detail, const QVector &labelShape, + const VTextManager &tm); + void PlotLabelSVGFont(QTextStream &out, const VLayoutPiece &detail, const QVector &labelShape, + const VTextManager &tm); + void PlotLabelOutlineFont(QTextStream &out, const VLayoutPiece &detail, const QVector &labelShape, + const VTextManager &tm); + + template auto ConvertPath(const QVector &path) const -> QVector; + template auto ConvertPoint(T point) const -> T; + void PlotPath(QTextStream &out, QVector path, Qt::PenStyle penStyle); + void PlotSolidLinePath(QTextStream &out, QVector path); + void PlotPathForStyle(QTextStream &out, QVector path, QVector pattern); + void PlotPainterPath(QTextStream &out, const QPainterPath &path, Qt::PenStyle penStyle); + + void HPPenUp(QTextStream &out, QPoint point); + void HPPenUp(QTextStream &out); + + void HPPenDown(QTextStream &out, QPoint point); + void HPPenDown(QTextStream &out); + + auto PatternForStyle(Qt::PenStyle style) const -> QVector; +}; + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VHPGLEngine::isActive() const -> bool +{ + return m_active; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline void VHPGLEngine::setActive(bool newState) +{ + m_active = newState; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VHPGLEngine::GetSize() const -> QSize +{ + return m_size; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline void VHPGLEngine::SetSize(QSize size) +{ + Q_ASSERT(not isActive()); + m_size = size; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VHPGLEngine::GetFileName() const -> QString +{ + return m_fileName; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline void VHPGLEngine::SetFileName(const QString &filename) +{ + Q_ASSERT(not isActive()); + m_fileName = filename; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline void VHPGLEngine::SetIsertNewLine(bool insert) +{ + Q_ASSERT(not isActive()); + m_inserNewLine = insert; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VHPGLEngine::GetSingleLineFont() const -> bool +{ + return m_singleLineFont; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline void VHPGLEngine::SetSingleLineFont(bool singleLineFont) +{ + Q_ASSERT(not isActive()); + m_singleLineFont = singleLineFont; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VHPGLEngine::GetSingleStrokeOutlineFont() const -> bool +{ + return m_singleStrokeOutlineFont; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline void VHPGLEngine::SetSingleStrokeOutlineFont(bool singleStrokeOutlineFont) +{ + Q_ASSERT(not isActive()); + m_singleStrokeOutlineFont = singleStrokeOutlineFont; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VHPGLEngine::GetPenWidth() const -> int +{ + return m_penWidthPx; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline void VHPGLEngine::SetPenWidth(int newPenWidth) +{ + m_penWidthPx = newPenWidth; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VHPGLEngine::GetXScale() const -> qreal +{ + return m_xscale; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline void VHPGLEngine::SetXScale(const qreal &xscale) +{ + Q_ASSERT(not isActive()); + m_xscale = xscale; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VHPGLEngine::GetYScale() const -> qreal +{ + return m_yscale; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline void VHPGLEngine::SetYScale(const qreal &yscale) +{ + Q_ASSERT(not isActive()); + m_yscale = yscale; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VHPGLEngine::GetShowGrainline() const -> bool +{ + return m_showGrainline; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline void VHPGLEngine::SetShowGrainline(bool newShowGrainline) +{ + Q_ASSERT(not isActive()); + m_showGrainline = newShowGrainline; +} + +#endif // VHPGLENGINE_H diff --git a/src/libs/vhpgl/vhpglpaintdevice.cpp b/src/libs/vhpgl/vhpglpaintdevice.cpp new file mode 100644 index 000000000..8c73798de --- /dev/null +++ b/src/libs/vhpgl/vhpglpaintdevice.cpp @@ -0,0 +1,201 @@ +/************************************************************************ + ** + ** @file vhpglpaintdevice.cpp + ** @author Roman Telezhynskyi + ** @date 7 7, 2020 + ** + ** @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 + ** 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 . + ** + *************************************************************************/ + +#include "vhpglpaintdevice.h" +#include "vhpglengine.h" + +//--------------------------------------------------------------------------------------------------------------------- +VHPGLPaintDevice::VHPGLPaintDevice() + : m_engine(new VHPGLEngine()) +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +VHPGLPaintDevice::~VHPGLPaintDevice() +{ + delete m_engine; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLPaintDevice::SetFileName(const QString &filename) +{ + if (m_engine->isActive()) + { + qWarning("VHPGLPaintDevice::SetFileName(), cannot set file name while HPGL is being generated"); + return; + } + + m_engine->SetFileName(filename); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VHPGLPaintDevice::GetSingleLineFont() const -> bool +{ + return m_engine->GetSingleLineFont(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLPaintDevice::SetSingleLineFont(bool singleLineFont) +{ + if (m_engine->isActive()) + { + qWarning( + "VHPGLPaintDevice::SetSingleLineFont(), cannot set single line font mode while HPGL is being generated"); + return; + } + m_engine->SetSingleLineFont(singleLineFont); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VHPGLPaintDevice::GetSingleStrokeOutlineFont() const -> bool +{ + return m_engine->GetSingleStrokeOutlineFont(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLPaintDevice::SetSingleStrokeOutlineFont(bool singleStrokeOutlineFont) +{ + if (m_engine->isActive()) + { + qWarning("VHPGLPaintDevice::SetSingleLineFont(), cannot set single stroke outline font mode while HPGL is " + "being generated"); + return; + } + m_engine->SetSingleStrokeOutlineFont(singleStrokeOutlineFont); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VHPGLPaintDevice::GetPenWidth() const -> int +{ + return m_engine->GetPenWidth(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLPaintDevice::SetPenWidth(int newPenWidth) +{ + if (m_engine->isActive()) + { + qWarning("VHPGLPaintDevice::SetSingleLineFont(), cannot set pen width while HPGL is " + "being generated"); + return; + } + m_engine->SetPenWidth(newPenWidth); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VHPGLPaintDevice::ExportToHPGL(const QVector &details) const -> bool +{ + m_engine->setActive(true); + const bool res = m_engine->GenerateHPGL(details); + m_engine->setActive(false); + return res; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VHPGLPaintDevice::ExportToHPGL2(const QVector &details) const -> bool +{ + m_engine->setActive(true); + const bool res = m_engine->GenerateHPGL2(details); + m_engine->setActive(false); + return res; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VHPGLPaintDevice::GetFileName() const -> QString +{ + return m_engine->GetFileName(); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VHPGLPaintDevice::GetSize() const -> QSize +{ + return m_engine->GetSize(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLPaintDevice::SetSize(QSize size) +{ + if (m_engine->isActive()) + { + qWarning("VHPGLPaintDevice::setSize(), cannot set size while HPGL is being generated"); + return; + } + m_engine->SetSize(size); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VHPGLPaintDevice::GetXScale() const -> qreal +{ + return m_engine->GetYScale(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLPaintDevice::SetXScale(const qreal &xscale) +{ + if (m_engine->isActive()) + { + qWarning("VHPGLPaintDevice::SetXScale(), cannot set x scale while HPGL is being generated"); + return; + } + m_engine->SetXScale(xscale); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VHPGLPaintDevice::GetYScale() const -> qreal +{ + return m_engine->GetXScale(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLPaintDevice::SetYScale(const qreal &yscale) +{ + if (m_engine->isActive()) + { + qWarning("VHPGLPaintDevice::SetYScale(), cannot set y scale while HPGL is being generated"); + return; + } + m_engine->SetYScale(yscale); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VHPGLPaintDevice::GetShowGrainline() const -> bool +{ + return m_engine->GetShowGrainline(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLPaintDevice::SetShowGrainline(bool newShowGrainline) +{ + if (m_engine->isActive()) + { + qWarning( + "VHPGLPaintDevice::SetShowGrainline(), cannot control grainline visibility while HPGL is being generated"); + return; + } + m_engine->SetShowGrainline(newShowGrainline); +} diff --git a/src/libs/vhpgl/vhpglpaintdevice.h b/src/libs/vhpgl/vhpglpaintdevice.h new file mode 100644 index 000000000..7c481f976 --- /dev/null +++ b/src/libs/vhpgl/vhpglpaintdevice.h @@ -0,0 +1,79 @@ +/************************************************************************ + ** + ** @file vhpglpaintdevice.h + ** @author Roman Telezhynskyi + ** @date 7 7, 2020 + ** + ** @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 + ** 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 . + ** + *************************************************************************/ +#ifndef VHPGLPAINTDEVICE_H +#define VHPGLPAINTDEVICE_H + +#include + +#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0) +#include "../vmisc/defglobal.h" +#endif + +class VHPGLEngine; +class QSize; +class VLayoutPiece; + +class VHPGLPaintDevice +{ +public: + VHPGLPaintDevice(); + ~VHPGLPaintDevice(); + + auto GetSize() const -> QSize; + void SetSize(QSize size); + + auto GetFileName() const -> QString; + void SetFileName(const QString &filename); + + auto GetSingleLineFont() const -> bool; + void SetSingleLineFont(bool singleLineFont); + + auto GetSingleStrokeOutlineFont() const -> bool; + void SetSingleStrokeOutlineFont(bool singleStrokeOutlineFont); + + auto GetPenWidth() const -> int; + void SetPenWidth(int newPenWidth); + + auto GetXScale() const -> qreal; + void SetXScale(const qreal &xscale); + + auto GetYScale() const -> qreal; + void SetYScale(const qreal &yscale); + + auto GetShowGrainline() const -> bool; + void SetShowGrainline(bool newShowGrainline); + + auto ExportToHPGL(const QVector &details) const -> bool; + auto ExportToHPGL2(const QVector &details) const -> bool; + +private: + Q_DISABLE_COPY_MOVE(VHPGLPaintDevice) // NOLINT + VHPGLEngine *m_engine; +}; + +#endif // VHPGLPAINTDEVICE_H diff --git a/src/libs/vhpgl/warnings.pri b/src/libs/vhpgl/warnings.pri new file mode 100644 index 000000000..f4a43deba --- /dev/null +++ b/src/libs/vhpgl/warnings.pri @@ -0,0 +1,83 @@ +#Turn on compilers warnings. +unix { + *g++*{ + QMAKE_CXXFLAGS += \ + # Key -isystem disable checking errors in system headers. + -isystem "$${OUT_PWD}/$${MOC_DIR}" \ + $$GCC_DEBUG_CXXFLAGS # See common.pri for more details. + + checkWarnings{ # For enable run qmake with CONFIG+=checkWarnings + QMAKE_CXXFLAGS += -Werror + } + + noAddressSanitizer{ # For enable run qmake with CONFIG+=noAddressSanitizer + # do nothing + } else { + CONFIG(debug, debug|release){ + # Debug mode + #gcc’s 4.8.0 Address Sanitizer + #http://blog.qt.digia.com/blog/2013/04/17/using-gccs-4-8-0-address-sanitizer-with-qt/ + QMAKE_CXXFLAGS += -fsanitize=address -fno-omit-frame-pointer + QMAKE_CFLAGS += -fsanitize=address -fno-omit-frame-pointer + QMAKE_LFLAGS += -fsanitize=address + } + } + + gccUbsan{ # For enable run qmake with CONFIG+=gccUbsan + CONFIG(debug, debug|release){ + # Debug mode + #gcc’s 4.9.0 Undefined Behavior Sanitizer (ubsan) + QMAKE_CXXFLAGS += -fsanitize=undefined + QMAKE_CFLAGS += -fsanitize=undefined + QMAKE_LFLAGS += -fsanitize=undefined + } + } + + # -isystem key works only for headers. In some cases it's not enough. But we can't delete this warnings and + # want them in global list. Compromise decision delete them from local list. + QMAKE_CXXFLAGS -= \ + -Wswitch-default + } + + *clang*{ + QMAKE_CXXFLAGS += \ + # Key -isystem disable checking errors in system headers. + -isystem "$${OUT_PWD}/$${MOC_DIR}" \ + $$CLANG_DEBUG_CXXFLAGS # See common.pri for more details. + + checkWarnings{ # For enable run qmake with CONFIG+=checkWarnings + QMAKE_CXXFLAGS += -Werror + } + + # -isystem key works only for headers. In some cases it's not enough. But we can't delete these warnings and + # want them in global list. Compromise decision delete them from local list. + QMAKE_CXXFLAGS -= \ + -Wundefined-reinterpret-cast + } + + *-icc-*{ + QMAKE_CXXFLAGS += \ + -isystem "$${OUT_PWD}/$${MOC_DIR}" \ + $$ICC_DEBUG_CXXFLAGS + + checkWarnings{ # For enable run qmake with CONFIG+=checkWarnings + QMAKE_CXXFLAGS += -Werror + } + } +} else { # Windows + *g++*{ + QMAKE_CXXFLAGS += $$GCC_DEBUG_CXXFLAGS # See common.pri for more details. + + checkWarnings{ # For enable run qmake with CONFIG+=checkWarnings + QMAKE_CXXFLAGS += -Werror + } + } + + *msvc*{ + QMAKE_CXXFLAGS += $$MSVC_DEBUG_CXXFLAGS # See common.pri for more details. + + checkWarnings{ # For enable run qmake with CONFIG+=checkWarnings + QMAKE_CXXFLAGS += -WX + } + } +} diff --git a/src/libs/vlayout/vlayout.qbs b/src/libs/vlayout/vlayout.qbs index 1bd442ece..556468847 100644 --- a/src/libs/vlayout/vlayout.qbs +++ b/src/libs/vlayout/vlayout.qbs @@ -6,6 +6,7 @@ VLib { Depends { name: "VObjLib" } Depends { name: "QMUParserLib" } Depends { name: "VDXFLib" } + Depends { name: "VHPGLLib"} Depends { name: "IFCLib" } Depends { name: "VWidgetsLib" } Depends { name: "VFormatLib" } diff --git a/src/libs/vlayout/vlayoutdef.h b/src/libs/vlayout/vlayoutdef.h index fcedbfd62..98afcbe9d 100644 --- a/src/libs/vlayout/vlayoutdef.h +++ b/src/libs/vlayout/vlayoutdef.h @@ -58,6 +58,8 @@ enum class LayoutExportFormats : qint8 NC = 34, /*G-code. Reserved for future*/ RLD = 35, /*Raw Layout Data*/ TIF = 36, + HPGL = 37, + HPGL2 = 38, COUNT /*Use only for validation*/ }; diff --git a/src/libs/vlayout/vlayoutexporter.cpp b/src/libs/vlayout/vlayoutexporter.cpp index 795df4b39..9cb3afb0a 100644 --- a/src/libs/vlayout/vlayoutexporter.cpp +++ b/src/libs/vlayout/vlayoutexporter.cpp @@ -43,6 +43,7 @@ #include "../ifc/exception/vexception.h" #include "../vdxf/vdxfpaintdevice.h" +#include "../vhpgl/vhpglpaintdevice.h" #include "../vmisc/def.h" #include "../vmisc/defglobal.h" #include "../vmisc/vabstractapplication.h" @@ -368,6 +369,42 @@ void VLayoutExporter::ExportToRLD(const QVector &details) const } } +//--------------------------------------------------------------------------------------------------------------------- +void VLayoutExporter::ExportToHPGL(const QVector &details) const +{ + VHPGLPaintDevice generator; + generator.SetFileName(m_fileName); + generator.SetSize(QSize(qCeil(m_imageRect.width() * m_xScale), qCeil(m_imageRect.height() * m_yScale))); + generator.SetXScale(m_xScale); + generator.SetYScale(m_yScale); + generator.SetShowGrainline(m_showGrainline); + generator.SetSingleLineFont(m_singleLineFont); + generator.SetSingleStrokeOutlineFont(m_singleStrokeOutlineFont); + generator.SetPenWidth(m_penWidth); + if (not generator.ExportToHPGL(details)) + { + qCritical() << tr("Can't create an HP-GL file."); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VLayoutExporter::ExportToHPGL2(const QVector &details) const +{ + VHPGLPaintDevice generator; + generator.SetFileName(m_fileName); + generator.SetSize(QSize(qCeil(m_imageRect.width() * m_xScale), qCeil(m_imageRect.height() * m_yScale))); + generator.SetXScale(m_xScale); + generator.SetYScale(m_yScale); + generator.SetShowGrainline(m_showGrainline); + generator.SetSingleLineFont(m_singleLineFont); + generator.SetSingleStrokeOutlineFont(m_singleStrokeOutlineFont); + generator.SetPenWidth(m_penWidth); + if (not generator.ExportToHPGL2(details)) + { + qCritical() << tr("Can't create an HP-GL file."); + } +} + //--------------------------------------------------------------------------------------------------------------------- auto VLayoutExporter::SupportPDFConversion() -> bool { @@ -393,18 +430,6 @@ auto VLayoutExporter::SupportPDFConversion() -> bool return res; } -//--------------------------------------------------------------------------------------------------------------------- -auto VLayoutExporter::offset() const -> QPointF -{ - return m_offset; -} - -//--------------------------------------------------------------------------------------------------------------------- -void VLayoutExporter::SetOffset(const QPointF &newOffset) -{ - m_offset = newOffset; -} - //--------------------------------------------------------------------------------------------------------------------- /** * @brief PdfToPs use external tool "pdftops" for converting pdf too eps or ps format. @@ -506,7 +531,6 @@ void VLayoutExporter::ExportToPDF(QGraphicsScene *scene, const QList QString { - const QString dxfSuffix = QStringLiteral("(*.dxf)"); const QString dxfFlatFilesStr = tr("(flat) files"); const QString filesStr = tr("files"); @@ -525,27 +549,27 @@ auto VLayoutExporter::ExportFormatDescription(LayoutExportFormats format) -> QSt case LayoutExportFormats::EPS: return QStringLiteral("EPS %1 (*.eps)").arg(filesStr); case LayoutExportFormats::DXF_AC1006_Flat: - return QStringLiteral("AutoCAD DXF R10 %1 %2").arg(dxfFlatFilesStr, dxfSuffix); + return QStringLiteral("AutoCAD DXF R10 %1 (*.dxf)").arg(dxfFlatFilesStr); case LayoutExportFormats::DXF_AC1009_Flat: - return QStringLiteral("AutoCAD DXF R11/12 %1 %2").arg(dxfFlatFilesStr, dxfSuffix); + return QStringLiteral("AutoCAD DXF R11/12 %1 (*.dxf)").arg(dxfFlatFilesStr); case LayoutExportFormats::DXF_AC1012_Flat: - return QStringLiteral("AutoCAD DXF R13 %1 %2").arg(dxfFlatFilesStr, dxfSuffix); + return QStringLiteral("AutoCAD DXF R13 %1 (*.dxf)").arg(dxfFlatFilesStr); case LayoutExportFormats::DXF_AC1014_Flat: - return QStringLiteral("AutoCAD DXF R14 %1 %2").arg(dxfFlatFilesStr, dxfSuffix); + return QStringLiteral("AutoCAD DXF R14 %1 (*.dxf)").arg(dxfFlatFilesStr); case LayoutExportFormats::DXF_AC1015_Flat: - return QStringLiteral("AutoCAD DXF 2000 %1 %2").arg(dxfFlatFilesStr, dxfSuffix); + return QStringLiteral("AutoCAD DXF 2000 %1 (*.dxf)").arg(dxfFlatFilesStr); case LayoutExportFormats::DXF_AC1018_Flat: - return QStringLiteral("AutoCAD DXF 2004 %1 %2").arg(dxfFlatFilesStr, dxfSuffix); + return QStringLiteral("AutoCAD DXF 2004 %1 (*.dxf)").arg(dxfFlatFilesStr); case LayoutExportFormats::DXF_AC1021_Flat: - return QStringLiteral("AutoCAD DXF 2007 %1 %2").arg(dxfFlatFilesStr, dxfSuffix); + return QStringLiteral("AutoCAD DXF 2007 %1 (*.dxf)").arg(dxfFlatFilesStr); case LayoutExportFormats::DXF_AC1024_Flat: - return QStringLiteral("AutoCAD DXF 2010 %1 %2").arg(dxfFlatFilesStr, dxfSuffix); + return QStringLiteral("AutoCAD DXF 2010 %1 (*.dxf)").arg(dxfFlatFilesStr); case LayoutExportFormats::DXF_AC1027_Flat: - return QStringLiteral("AutoCAD DXF 2013 %1 %2").arg(dxfFlatFilesStr, dxfSuffix); + return QStringLiteral("AutoCAD DXF 2013 %1 (*.dxf)").arg(dxfFlatFilesStr); case LayoutExportFormats::DXF_AAMA: - return QStringLiteral("AutoCAD DXF AAMA %1 %2").arg(filesStr, dxfSuffix); + return QStringLiteral("AutoCAD DXF AAMA %1 (*.dxf)").arg(filesStr); case LayoutExportFormats::DXF_ASTM: - return QStringLiteral("AutoCAD DXF ASTM %1 %2").arg(filesStr, dxfSuffix); + return QStringLiteral("AutoCAD DXF ASTM %1 (*.dxf)").arg(filesStr); case LayoutExportFormats::PDFTiled: return QStringLiteral("PDF %1 %2 (*.pdf)").arg(tr("tiled"), filesStr); case LayoutExportFormats::NC: @@ -554,6 +578,10 @@ auto VLayoutExporter::ExportFormatDescription(LayoutExportFormats format) -> QSt return QStringLiteral("%1 %2 (*.rld)").arg(tr("Raw Layout Data"), filesStr); case LayoutExportFormats::TIF: return QStringLiteral("TIFF %1 (*.tif)").arg(filesStr); + case LayoutExportFormats::HPGL: + return QStringLiteral("HP-GL %1 (*.hpgl)").arg(filesStr); + case LayoutExportFormats::HPGL2: + return QStringLiteral("HP-GL/2 %1 (*.hpgl)").arg(filesStr); default: return {}; } @@ -595,6 +623,9 @@ auto VLayoutExporter::ExportFormatSuffix(LayoutExportFormats format) -> QString return QStringLiteral(".rld"); case LayoutExportFormats::TIF: return QStringLiteral(".tif"); + case LayoutExportFormats::HPGL: + case LayoutExportFormats::HPGL2: + return QStringLiteral(".hpgl"); default: return {}; } diff --git a/src/libs/vlayout/vlayoutexporter.h b/src/libs/vlayout/vlayoutexporter.h index 6e8ed1c7d..7e2db46e9 100644 --- a/src/libs/vlayout/vlayoutexporter.h +++ b/src/libs/vlayout/vlayoutexporter.h @@ -94,6 +94,8 @@ public: void ExportToAAMADXF(const QVector &details) const; void ExportToASTMDXF(const QVector &details) const; void ExportToRLD(const QVector &details) const; + void ExportToHPGL(const QVector &details) const; + void ExportToHPGL2(const QVector &details) const; static auto SupportPDFConversion() -> bool; @@ -106,6 +108,15 @@ public: auto offset() const -> QPointF; void SetOffset(const QPointF &newOffset); + auto GetSingleLineFont() const -> bool; + void SetSingleLineFont(bool newSingleLineFont); + + auto GetSingleStrokeOutlineFont() const -> bool; + void SetSingleStrokeOutlineFont(bool newSingleStrokeOutlineFont); + + auto GetPenWidth() const -> int; + void SetPenWidth(int newPenWidth); + private: QString m_fileName{}; QMarginsF m_margins{}; @@ -120,6 +131,9 @@ private: bool m_showGrainline{true}; int m_dxfVersion{0}; QPointF m_offset{}; + bool m_singleLineFont{false}; + bool m_singleStrokeOutlineFont{false}; + int m_penWidth{1}; void ExportToPDF(QGraphicsScene *scene, const QList &details, const QString &filename) const; }; @@ -256,4 +270,52 @@ inline void VLayoutExporter::SetDxfVersion(int dxfVersion) m_dxfVersion = dxfVersion; } +//--------------------------------------------------------------------------------------------------------------------- +inline auto VLayoutExporter::offset() const -> QPointF +{ + return m_offset; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline void VLayoutExporter::SetOffset(const QPointF &newOffset) +{ + m_offset = newOffset; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VLayoutExporter::GetSingleLineFont() const -> bool +{ + return m_singleLineFont; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline void VLayoutExporter::SetSingleLineFont(bool newSingleLineFont) +{ + m_singleLineFont = newSingleLineFont; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VLayoutExporter::GetSingleStrokeOutlineFont() const -> bool +{ + return m_singleStrokeOutlineFont; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline void VLayoutExporter::SetSingleStrokeOutlineFont(bool newSingleStrokeOutlineFont) +{ + m_singleStrokeOutlineFont = newSingleStrokeOutlineFont; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline int VLayoutExporter::GetPenWidth() const +{ + return m_penWidth; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline void VLayoutExporter::SetPenWidth(int newPenWidth) +{ + m_penWidth = newPenWidth; +} + #endif // VLAYOUTEXPORTER_H diff --git a/src/libs/vlayout/vlayoutpiece.cpp b/src/libs/vlayout/vlayoutpiece.cpp index 65e2fe0de..391e52869 100644 --- a/src/libs/vlayout/vlayoutpiece.cpp +++ b/src/libs/vlayout/vlayoutpiece.cpp @@ -721,18 +721,6 @@ auto VLayoutPiece::GetUniqueID() const -> QString return id; } -//--------------------------------------------------------------------------------------------------------------------- -template auto VLayoutPiece::Map(QVector points) const -> QVector -{ - std::transform(points.begin(), points.end(), points.begin(), - [this](const T &point) { return d->m_matrix.map(point); }); - if (d->m_mirror) - { - std::reverse(points.begin(), points.end()); - } - return points; -} - //--------------------------------------------------------------------------------------------------------------------- template <> // NOLINTNEXTLINE(readability-inconsistent-declaration-parameter-name) auto VLayoutPiece::Map(QVector passmarks) const -> QVector @@ -1958,3 +1946,9 @@ auto VLayoutPiece::EdgeByPoint(const QVector &path, const QPointF &p1) } return {}; // Did not find edge } + +//--------------------------------------------------------------------------------------------------------------------- +template auto VLayoutPiece::Map(QVector points) const -> QVector +{ + return Map(points, d->m_matrix, d->m_mirror); +} diff --git a/src/libs/vlayout/vlayoutpiece.h b/src/libs/vlayout/vlayoutpiece.h index 13d146df6..14ea94178 100644 --- a/src/libs/vlayout/vlayoutpiece.h +++ b/src/libs/vlayout/vlayoutpiece.h @@ -64,6 +64,16 @@ class VAbstractPattern; class VPatternLabelData; class VLayoutPoint; +template struct IsLayoutPoint +{ + static const bool value = false; +}; + +template <> struct IsLayoutPoint +{ + static const bool value = true; +}; + QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wsuggest-final-types") QT_WARNING_DISABLE_GCC("-Wsuggest-final-methods") @@ -158,6 +168,18 @@ public: auto GetYScale() const -> qreal; void SetYScale(qreal ys); + auto GetPieceLabelRect() const -> QVector; + void SetPieceLabelRect(const QVector &rect); + + auto GetPieceLabelData() const -> VTextManager; + void SetPieceLabelData(const VTextManager &data); + + auto GetPatternLabelRect() const -> QVector; + void SetPatternLabelRect(const QVector &rect); + + auto GetPatternLabelData() const -> VTextManager; + void SetPatternLabelData(const VTextManager &data); + void Translate(const QPointF &p); void Translate(qreal dx, qreal dy); void Scale(qreal sx, qreal sy); @@ -200,21 +222,17 @@ public: auto MapPlaceLabelShape(PlaceLabelImg shape) const -> PlaceLabelImg; + template static auto Map(QVector points, const QTransform &matrix, bool mirror) -> QVector; + + template + static auto Map(T obj, const QTransform &matrix) -> typename std::enable_if::value, T>::type; + + template + static auto Map(T obj, const QTransform &matrix) -> typename std::enable_if::value, T>::type; + protected: void SetGrainline(const VPieceGrainline &grainline); - auto GetPieceLabelRect() const -> QVector; - void SetPieceLabelRect(const QVector &rect); - - auto GetPieceLabelData() const -> VTextManager; - void SetPieceLabelData(const VTextManager &data); - - auto GetPatternLabelRect() const -> QVector; - void SetPatternLabelRect(const QVector &rect); - - auto GetPatternLabelData() const -> VTextManager; - void SetPatternLabelData(const VTextManager &data); - private: QSharedDataPointer d; @@ -243,4 +261,33 @@ QT_WARNING_POP Q_DECLARE_TYPEINFO(VLayoutPiece, Q_MOVABLE_TYPE); // NOLINT +//--------------------------------------------------------------------------------------------------------------------- +template inline auto VLayoutPiece::Map(QVector points, const QTransform &matrix, bool mirror) -> QVector +{ + std::transform(points.begin(), points.end(), points.begin(), + [matrix](const T &point) { return Map(point, matrix); }); + if (mirror) + { + std::reverse(points.begin(), points.end()); + } + return points; +} + +//--------------------------------------------------------------------------------------------------------------------- +template +auto VLayoutPiece::Map(T obj, const QTransform &matrix) -> typename std::enable_if::value, T>::type +{ + return matrix.map(obj); +} + +//--------------------------------------------------------------------------------------------------------------------- +template +auto VLayoutPiece::Map(T obj, const QTransform &matrix) -> typename std::enable_if::value, T>::type +{ + auto p = matrix.map(obj); + obj.setX(p.x()); + obj.setY(p.y()); + return obj; +} + #endif // VLAYOUTDETAIL_H