Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pattern pieces grouped in exported SVGs #1195

Merged
merged 7 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 19 additions & 16 deletions src/app/seamly2d/mainwindowsnogui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
#include "../vpatterndb/measurements_def.h"
#include "../vtools/tools/vabstracttool.h"
#include "../vtools/tools/pattern_piece_tool.h"
#include "../../libs/vformat/svg_generator.h"

#include <QFileDialog>
#include <QFileInfo>
Expand Down Expand Up @@ -888,21 +889,23 @@ QList<QGraphicsScene *> MainWindowsNoGUI::CreateScenes(const QList<QGraphicsItem
*/
void MainWindowsNoGUI::exportSVG(const QString &name, QGraphicsRectItem *paper, QGraphicsScene *scene) const
{
QSvgGenerator generator;
generator.setFileName(name);
generator.setSize(paper->rect().size().toSize());
generator.setViewBox(paper->rect());
generator.setTitle(tr("Pattern"));
generator.setDescription(doc->GetDescription());
generator.setResolution(static_cast<int>(PrintDPI));
QPainter painter;
painter.begin(&generator);
painter.setFont( QFont( "Arial", 8, QFont::Normal ) );
painter.setRenderHint(QPainter::Antialiasing, true);
//painter.setPen(QPen(Qt::black, widthHairLine, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter.setBrush ( QBrush ( Qt::NoBrush ) );
scene->render(&painter, paper->rect(), paper->rect(), Qt::IgnoreAspectRatio);
painter.end();
SvgGenerator svgGenerator(paper, name, doc->GetDescription(), static_cast<int>(PrintDPI));
svgGenerator.addSvgFromScene(scene);
svgGenerator.generate();
}

void MainWindowsNoGUI::exportSVG(const QString &name, QGraphicsRectItem *paper, const QList<QGraphicsItem *> &pieces) const
{
SvgGenerator svgGenerator(paper, name, doc->GetDescription(), static_cast<int>(PrintDPI));

for (int pieceNb=0; pieceNb<pieces.size(); pieceNb++)
{
QGraphicsScene *scene = new VMainGraphicsScene();
scene->addItem(pieces.at(pieceNb));
svgGenerator.addSvgFromScene(scene);
}

svgGenerator.generate();
}

//---------------------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -1633,7 +1636,7 @@ void MainWindowsNoGUI::ExportScene(const ExportLayoutDialog &dialog, const QList
{
case LayoutExportFormat::SVG:
paper->setVisible(false);
exportSVG(name, paper, scene);
exportSVG(name, paper, pieces.at(i));
paper->setVisible(true);
break;
case LayoutExportFormat::PDF:
Expand Down
1 change: 1 addition & 0 deletions src/app/seamly2d/mainwindowsnogui.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ public slots:
void refreshGrainLines();
void refreshSeamAllowances();
void exportSVG(const QString &name, QGraphicsRectItem *paper, QGraphicsScene *scene)const;
void exportSVG(const QString &name, QGraphicsRectItem *paper, const QList<QGraphicsItem *> &pieces)const;
void exportPNG(const QString &name, QGraphicsScene *scene)const;
void exportTIF(const QString &name, QGraphicsScene *scene)const;
void exportJPG(const QString &name, QGraphicsScene *scene)const;
Expand Down
182 changes: 182 additions & 0 deletions src/libs/vformat/svg_generator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
/******************************************************************************
** @file svg_generator.cpp
** @author Evans PERRET
** @date September 21, 2024
**
** @brief
** @copyright
** This source code is part of the Seamly2D project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2013-2022 Seamly2D project
** <https://github.com/fashionfreedom/seamly2d> All Rights Reserved.
**
** Seamly2D 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.
**
** Seamly2D 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 Seamly2D. If not, see <http://www.gnu.org/licenses/>.
**
*****************************************************************************/

#include "svg_generator.h"
#include <QFile>
#include <QDir>
#include <QDebug>
#include <QSvgGenerator>
#include <QGraphicsItem>
#include <QPainter>
#include <QFileInfo>

SvgGenerator::SvgGenerator(QGraphicsRectItem *paper, QString name, QString description, int resolution):
m_svgCounter(0),
m_paper(paper),
m_filepath(name),
m_description(description),
m_resolution(resolution),
m_tempSvgPrefix("tempSvg")
{
QFileInfo fileInfo(m_filepath);
m_folderPath = fileInfo.absolutePath();
m_name = fileInfo.baseName();
m_tempSvgFolderName = m_tempSvgPrefix + "_" + m_name;
}


bool SvgGenerator::loadSvgIntoDom(QDomDocument &domDocument, const QString &filePath)
{
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly)) {
qDebug() << "Error : Impossible to open the SVG file :" << filePath;
return false;
}
if (!domDocument.setContent(&file)) {
qDebug() << "Error : Impossible to load the SVG content in the QDomDocument.";
file.close();
return false;
}
file.close();
return true;
}

QDomDocument SvgGenerator::mergeSvgDoms(const QList<QDomDocument> &domList)
{
/*domList contains DOM representations of multiple SVG
Assuming each svg contains a main group containing every graphical item of the svg,
this function adds to the first svg of the list all the main groups of the other svgs,
thus creating a single svg with each svg of the list in it, every svg being in its own group.
This function is used in order to create svgs containing groups*/

if (domList.isEmpty()) {
qDebug() << "Error : the SVG list is empty";
return QDomDocument();
}

QDomDocument mergedSvg = domList.at(0);

QDomElement mergedSvgRoot = mergedSvg.documentElement();
if (mergedSvgRoot.tagName() != "svg") {
qDebug() << "Error : the first SVG does not contain a <svg> tag.";
return QDomDocument();
}

for (int i = 1; i < domList.size(); ++i) {
QDomDocument domSvg = domList.at(i);
QDomElement svgRoot = domSvg.documentElement();
if (svgRoot.tagName() != "svg") {
qDebug() << "Error : the SVG does not contain a <svg> tag.";
return QDomDocument();
}
QDomNodeList svgGroups = svgRoot.elementsByTagName("g");
if (svgGroups.isEmpty()) {
qDebug() << "Error : the SVG does not contain a <g> tag.";
return QDomDocument();
}
QDomElement mainGroup = svgGroups.at(0).toElement();
mergedSvgRoot.appendChild(mainGroup);
}

return mergedSvg;
}

void SvgGenerator::addSvgFromScene(QGraphicsScene *scene)
{
m_svgCounter++;

QSvgGenerator svgGenerator;
svgGenerator.setFileName(getTempFilePath(m_svgCounter));
svgGenerator.setSize(m_paper->rect().size().toSize());
svgGenerator.setViewBox(m_paper->rect());
svgGenerator.setTitle(QObject::tr("Pattern"));
svgGenerator.setDescription(m_description);
svgGenerator.setResolution(m_resolution);

QPainter painter;
painter.begin(&svgGenerator);
painter.setFont( QFont( "Arial", 8, QFont::Normal ) );
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setBrush ( QBrush ( Qt::NoBrush ) );
scene->render(&painter, m_paper->rect(), m_paper->rect(), Qt::IgnoreAspectRatio);
painter.end();
}


void SvgGenerator::generate()
{
QList<QDomDocument> domList;

for(int i = 1; i <= m_svgCounter; i++)
{
QDomDocument domDoc;
QString path = getTempFilePath(i);
QFile file(path);
if (!file.exists()) {
qDebug() << "Error : the SVG file does not exist.";
continue;
}
loadSvgIntoDom(domDoc, path);
domList.append(domDoc);

if (!file.remove()) {
qDebug() << "Error : unable to remove " << path;
}
}

QDomDocument mergedSvg = mergeSvgDoms(domList);

QFile outputFile(m_filepath);
if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
qDebug() << "Error : Couldn't write the output file.";
}

QTextStream stream(&outputFile);
stream << mergedSvg.toString();
outputFile.close();

QDir dir(m_folderPath);
if(!dir.rmdir(m_tempSvgFolderName))
{
qDebug() << "Error : Couldn't remove the temp SVG folder.";
}

qDebug() << "Merged SVG Generated!";
}


QString SvgGenerator::getTempFilePath(int id)
{
QDir dir(m_folderPath);
if (!dir.cd(m_tempSvgFolderName))
{
dir.mkdir(m_tempSvgFolderName);
dir.cd(m_tempSvgFolderName);
}

return dir.path() + "/" + m_tempSvgPrefix + "_" + m_name + "_" + QString::number(id) + ".svg";
}
59 changes: 59 additions & 0 deletions src/libs/vformat/svg_generator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/******************************************************************************
** @file svg_generator.h
** @author Evans PERRET
** @date September 21, 2024
**
** @brief
** @copyright
** This source code is part of the Seamly2D project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2013-2022 Seamly2D project
** <https://github.com/fashionfreedom/seamly2d> All Rights Reserved.
**
** Seamly2D 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.
**
** Seamly2D 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 Seamly2D. If not, see <http://www.gnu.org/licenses/>.
**
*****************************************************************************/

#ifndef SVG_GENERATOR_H
#define SVG_GENERATOR_H

#include <QDomDocument>
#include <QGraphicsScene>


class SvgGenerator
{
public:
SvgGenerator(QGraphicsRectItem *paper, QString name, QString description, int resolution);
void addSvgFromScene(QGraphicsScene *scene);
void generate();


private:
bool loadSvgIntoDom(QDomDocument &domDocument, const QString &filePath);
QDomDocument mergeSvgDoms(const QList<QDomDocument> &domList);
QString getTempFilePath(int id);

int m_svgCounter;
QGraphicsRectItem *m_paper;
QString m_filepath;
QString m_folderPath;
QString m_name;
QString m_description;
int m_resolution;
QString m_tempSvgFolderName;
QString m_tempSvgPrefix;
};

#endif // SVG_GENERATOR_H
2 changes: 2 additions & 0 deletions src/libs/vformat/vformat.pri
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@

SOURCES += \
$$PWD/measurements.cpp \
$$PWD/svg_generator.cpp \
$$PWD/vlabeltemplate.cpp

*msvc*:SOURCES += $$PWD/stable.cpp

HEADERS += \
$$PWD/measurements.h \
$$PWD/stable.h \
$$PWD/svg_generator.h \
$$PWD/vlabeltemplate.h
2 changes: 1 addition & 1 deletion src/libs/vformat/vformat.pro
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ message("Entering vformat.pro")
include(../../../common.pri)

# Library work with xml.
QT += xml xmlpatterns printsupport
QT += xml xmlpatterns printsupport svg

# We don't need gui library.
QT -= gui
Expand Down
Loading