diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 2502c1b3e..6ab5dad76 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -161,6 +161,8 @@ add_library(libslic3r STATIC utils.cpp Utils.hpp MTUtils.hpp + Zipper.hpp + Zipper.cpp SLA/SLABoilerPlate.hpp SLA/SLABasePool.hpp SLA/SLABasePool.cpp diff --git a/src/libslic3r/PrintExport.hpp b/src/libslic3r/PrintExport.hpp index df9446cf5..99a2110b3 100644 --- a/src/libslic3r/PrintExport.hpp +++ b/src/libslic3r/PrintExport.hpp @@ -97,7 +97,7 @@ public: bool is_ok() { return false; } - template LayerWriter& operator<<(const T& /*arg*/) { + template LayerWriter& operator<<(T&& /*arg*/) { return *this; } diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index eb927c769..a8f35a406 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -6,6 +6,7 @@ #include "PrintExport.hpp" #include "Point.hpp" #include "MTUtils.hpp" +#include "Zipper.hpp" namespace Slic3r { @@ -200,6 +201,32 @@ struct SLAPrintStatistics } }; +struct SLAminzFmt {}; + +// The implementation of creating zipped archives with wxWidgets +template<> class LayerWriter { + Zipper m_zip; +public: + + inline LayerWriter(const std::string& zipfile_path): m_zip(zipfile_path) {} + + inline void next_entry(const std::string& fname) { m_zip.add_entry(fname); } + + inline std::string get_name() const { + return m_zip.get_name(); + } + + template inline LayerWriter& operator<<(T&& arg) { + m_zip << std::forward(arg); return *this; + } + + bool is_ok() const { + return true; // m_zip blows up if something goes wrong... + } + + inline void close() { /* m_zip closes upon destruction */ } +}; + /** * @brief This class is the high level FSM for the SLA printing process. * @@ -231,9 +258,11 @@ public: // Returns true if the last step was finished with success. bool finished() const override { return this->is_step_done(slaposIndexSlices) && this->Inherited::is_step_done(slapsRasterize); } - template void export_raster(const std::string& fname) { + template + void export_raster(const std::string& fname) { if(m_printer) m_printer->save(fname); } + const PrintObjects& objects() const { return m_objects; } std::string output_filename() const override; diff --git a/src/libslic3r/Zipper.cpp b/src/libslic3r/Zipper.cpp new file mode 100644 index 000000000..2dd91c616 --- /dev/null +++ b/src/libslic3r/Zipper.cpp @@ -0,0 +1,68 @@ +#include +#include +#include + +#include "Zipper.hpp" +#include "miniz/miniz_zip.h" +#include + +namespace Slic3r { + +class Zipper::Impl { +public: + mz_zip_archive arch; +}; + +Zipper::Zipper(const std::string &zipfname, e_compression compression) +{ + m_impl.reset(new Impl()); + + memset(&m_impl->arch, 0, sizeof(m_impl->arch)); + + // Initialize the archive data + if(!mz_zip_writer_init_file(&m_impl->arch, zipfname.c_str(), 0)) + throw std::runtime_error("Cannot open zip archive!"); + + m_compression = compression; + m_zipname = zipfname; +} + +Zipper::~Zipper() +{ + finish_entry(); + mz_zip_writer_finalize_archive(&m_impl->arch); + mz_zip_writer_end(&m_impl->arch); +} + +void Zipper::add_entry(const std::string &name) +{ + finish_entry(); // finish previous business + m_entry = name; +} + +void Zipper::finish_entry() +{ + if(!m_data.empty() > 0 && !m_entry.empty()) { + mz_uint compression = MZ_NO_COMPRESSION; + + switch (m_compression) { + case NO_COMPRESSION: compression = MZ_NO_COMPRESSION; break; + case FAST_COMPRESSION: compression = MZ_BEST_SPEED; break; + case TIGHT_COMPRESSION: compression = MZ_BEST_COMPRESSION; break; + } + + mz_zip_writer_add_mem(&m_impl->arch, m_entry.c_str(), + m_data.c_str(), + m_data.size(), + compression); + } + + m_data.clear(); + m_entry.clear(); +} + +std::string Zipper::get_name() const { + return boost::filesystem::path(m_zipname).stem().string(); +} + +} diff --git a/src/libslic3r/Zipper.hpp b/src/libslic3r/Zipper.hpp new file mode 100644 index 000000000..d83e33e6b --- /dev/null +++ b/src/libslic3r/Zipper.hpp @@ -0,0 +1,51 @@ +#ifndef ZIPPER_HPP +#define ZIPPER_HPP + +#include +#include + +namespace Slic3r { + +class Zipper { +public: + enum e_compression { + NO_COMPRESSION, + FAST_COMPRESSION, + TIGHT_COMPRESSION + }; + +private: + class Impl; + std::unique_ptr m_impl; + std::string m_data; + std::string m_entry; + e_compression m_compression; + std::string m_zipname; + +public: + + // Will blow up in a runtime exception if the file cannot be created. + explicit Zipper(const std::string& zipfname, + e_compression level = NO_COMPRESSION); + ~Zipper(); + + Zipper(const Zipper&) = delete; + Zipper& operator=(const Zipper&) = delete; + + Zipper(Zipper&&) = default; + Zipper& operator=(Zipper&&) = default; + + void add_entry(const std::string& name); + void finish_entry(); + + inline Zipper& operator<<(const std::string& content) { + std::copy(content.begin(), content.end(), std::back_inserter(m_data)); + return *this; + } + + std::string get_name() const; +}; + +} + +#endif // ZIPPER_HPP diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index 7c2f6c68c..2ba1d6cdc 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -129,8 +129,8 @@ public: return fpath.GetName().ToUTF8().data(); } - template inline LayerWriter& operator<<(const T& arg) { - pngstream << arg; return *this; + template inline LayerWriter& operator<<(T&& arg) { + pngstream << std::forward(arg); return *this; } bool is_ok() const { @@ -149,7 +149,8 @@ void BackgroundSlicingProcess::process_sla() m_print->process(); if (this->set_step_started(bspsGCodeFinalize)) { if (! m_export_path.empty()) { - m_sla_print->export_raster(m_export_path); + // m_sla_print->export_raster(m_export_path); + m_sla_print->export_raster(m_export_path); m_print->set_status(100, "Masked SLA file exported to " + m_export_path); } else if (! m_upload_job.empty()) { prepare_upload(); @@ -450,7 +451,8 @@ void BackgroundSlicingProcess::prepare_upload() run_post_process_scripts(source_path.string(), m_fff_print->config()); m_upload_job.upload_data.upload_path = m_fff_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string()); } else { - m_sla_print->export_raster(source_path.string()); + // m_sla_print->export_raster(source_path.string()); + m_sla_print->export_raster(source_path.string()); // TODO: Also finalize upload path like with FFF when there are statistics for SLA print }