mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-24 01:01:15 -06:00
SLA archive import with miniz, marching square bugfixes
Fix compilation on Windows Fix array subscript out of range error in MarchingSquares Fix normals of mesh constructed from slices Improve performance of mesh construction from slices
This commit is contained in:
parent
247fca6d55
commit
217477a9ff
17 changed files with 690 additions and 373 deletions
|
|
@ -11,11 +11,11 @@ namespace marchsq {
|
|||
|
||||
// Marks a square in the grid
|
||||
struct Coord {
|
||||
size_t r = 0, c = 0;
|
||||
long r = 0, c = 0;
|
||||
|
||||
Coord() = default;
|
||||
explicit Coord(size_t s) : r(s), c(s) {}
|
||||
Coord(size_t _r, size_t _c): r(_r), c(_c) {}
|
||||
explicit Coord(long s) : r(s), c(s) {}
|
||||
Coord(long _r, long _c): r(_r), c(_c) {}
|
||||
|
||||
size_t seq(const Coord &res) const { return r * res.c + c; }
|
||||
Coord& operator+=(const Coord& b) { r += b.r; c += b.c; return *this; }
|
||||
|
|
@ -52,11 +52,6 @@ namespace __impl {
|
|||
template<class T> using RasterTraits = _RasterTraits<std::decay_t<T>>;
|
||||
template<class T> using TRasterValue = typename RasterTraits<T>::ValueType;
|
||||
|
||||
template<class T> TRasterValue<T> isoval(const T &raster, const Coord &crd)
|
||||
{
|
||||
return RasterTraits<T>::get(raster, crd.r, crd.c);
|
||||
}
|
||||
|
||||
template<class T> size_t rows(const T &raster)
|
||||
{
|
||||
return RasterTraits<T>::rows(raster);
|
||||
|
|
@ -67,6 +62,11 @@ template<class T> size_t cols(const T &raster)
|
|||
return RasterTraits<T>::cols(raster);
|
||||
}
|
||||
|
||||
template<class T> TRasterValue<T> isoval(const T &rst, const Coord &crd)
|
||||
{
|
||||
return RasterTraits<T>::get(rst, crd.r, crd.c);
|
||||
}
|
||||
|
||||
template<class ExecutionPolicy, class It, class Fn>
|
||||
void for_each(ExecutionPolicy&& policy, It from, It to, Fn &&fn)
|
||||
{
|
||||
|
|
@ -142,55 +142,46 @@ inline Coord step(const Coord &crd, Dir d)
|
|||
|
||||
template<class Rst> class Grid {
|
||||
const Rst * m_rst = nullptr;
|
||||
Coord m_cellsize, m_res_1, m_window, m_gridsize;
|
||||
Coord m_cellsize, m_res_1, m_window, m_gridsize, m_grid_1;
|
||||
std::vector<uint8_t> m_tags; // Assign tags to each square
|
||||
|
||||
Coord rastercoord(const Coord &crd) const
|
||||
{
|
||||
return {crd.r * m_window.r, crd.c * m_window.c};
|
||||
return {(crd.r - 1) * m_window.r, (crd.c - 1) * m_window.c};
|
||||
}
|
||||
|
||||
Coord bl(const Coord &crd) const { return tl(crd) + Coord{m_res_1.r, 0}; }
|
||||
Coord br(const Coord &crd) const { return tl(crd) + Coord{m_res_1.r, m_res_1.c}; }
|
||||
Coord tr(const Coord &crd) const { return tl(crd) + Coord{0, m_res_1.c}; }
|
||||
Coord tl(const Coord &crd) const { return rastercoord(crd); }
|
||||
|
||||
TRasterValue<Rst> bottomleft(const Coord &cell) const
|
||||
{
|
||||
return isoval(*m_rst, bl(cell));
|
||||
}
|
||||
|
||||
TRasterValue<Rst> bottomright(const Coord &cell) const
|
||||
bool is_within(const Coord &crd)
|
||||
{
|
||||
return isoval(*m_rst, br(cell));
|
||||
}
|
||||
|
||||
TRasterValue<Rst> topright(const Coord &cell) const
|
||||
{
|
||||
return isoval(*m_rst, tr(cell));
|
||||
}
|
||||
|
||||
TRasterValue<Rst> topleft(const Coord &cell) const
|
||||
{
|
||||
return isoval(*m_rst, tl(cell));
|
||||
}
|
||||
long R = rows(*m_rst), C = cols(*m_rst);
|
||||
return crd.r >= 0 && crd.r < R && crd.c >= 0 && crd.c < C;
|
||||
};
|
||||
|
||||
// Calculate the tag for a cell (or square). The cell coordinates mark the
|
||||
// top left vertex of a square in the raster. v is the isovalue
|
||||
uint8_t get_tag_for_cell(const Coord &cell, TRasterValue<Rst> v)
|
||||
{
|
||||
uint8_t t = (bottomleft(cell) >= v) +
|
||||
((bottomright(cell) >= v) << 1) +
|
||||
((topright(cell) >= v) << 2) +
|
||||
((topleft(cell) >= v) << 3);
|
||||
{
|
||||
Coord sqr[] = {bl(cell), br(cell), tr(cell), tl(cell)};
|
||||
|
||||
uint8_t t = ((is_within(sqr[0]) && isoval(*m_rst, sqr[0]) >= v)) +
|
||||
((is_within(sqr[1]) && isoval(*m_rst, sqr[1]) >= v) << 1) +
|
||||
((is_within(sqr[2]) && isoval(*m_rst, sqr[2]) >= v) << 2) +
|
||||
((is_within(sqr[3]) && isoval(*m_rst, sqr[3]) >= v) << 3);
|
||||
|
||||
assert(t < 16);
|
||||
return t;
|
||||
}
|
||||
|
||||
// Get a cell coordinate from a sequential index
|
||||
Coord coord(size_t i) const { return {i / m_gridsize.c, i % m_gridsize.c}; }
|
||||
|
||||
Coord coord(size_t i) const
|
||||
{
|
||||
return {long(i) / m_gridsize.c, long(i) % m_gridsize.c};
|
||||
}
|
||||
|
||||
size_t seq(const Coord &crd) const { return crd.seq(m_gridsize); }
|
||||
|
||||
bool is_visited(size_t idx, Dir d = Dir::none) const
|
||||
|
|
@ -217,7 +208,7 @@ template<class Rst> class Grid {
|
|||
{
|
||||
// Skip ambiguous tags as starting tags due to unknown previous
|
||||
// direction.
|
||||
while ((i < m_tags.size() && is_visited(i)) || is_ambiguous(i)) ++i;
|
||||
while ((i < m_tags.size()) && (is_visited(i) || is_ambiguous(i))) ++i;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
|
@ -248,8 +239,9 @@ template<class Rst> class Grid {
|
|||
}
|
||||
|
||||
struct CellIt {
|
||||
Coord crd; Dir dir= Dir::none; const Rst *rst = nullptr;
|
||||
TRasterValue<Rst> operator*() const { return isoval(*rst, crd); }
|
||||
Coord crd; Dir dir= Dir::none; const Rst *grid = nullptr;
|
||||
|
||||
TRasterValue<Rst> operator*() const { return isoval(*grid, crd); }
|
||||
CellIt& operator++() { crd = step(crd, dir); return *this; }
|
||||
CellIt operator++(int) { CellIt it = *this; ++(*this); return it; }
|
||||
bool operator!=(const CellIt &it) { return crd.r != it.crd.r || crd.c != it.crd.c; }
|
||||
|
|
@ -265,7 +257,7 @@ template<class Rst> class Grid {
|
|||
// used for binary search for the first active pixel on the edge.
|
||||
struct Edge { CellIt from, to; };
|
||||
|
||||
Edge edge(const Coord &ringvertex)
|
||||
Edge _edge(const Coord &ringvertex) const
|
||||
{
|
||||
size_t idx = ringvertex.r;
|
||||
Coord cell = coord(idx);
|
||||
|
|
@ -312,6 +304,28 @@ template<class Rst> class Grid {
|
|||
return {};
|
||||
}
|
||||
|
||||
Edge edge(const Coord &ringvertex) const
|
||||
{
|
||||
const long R = rows(*m_rst), C = cols(*m_rst);
|
||||
const long R_1 = R - 1, C_1 = C - 1;
|
||||
|
||||
Edge e = _edge(ringvertex);
|
||||
e.to.dir = e.from.dir;
|
||||
++e.to;
|
||||
|
||||
e.from.crd.r = std::min(e.from.crd.r, R_1);
|
||||
e.from.crd.r = std::max(e.from.crd.r, 0l);
|
||||
e.from.crd.c = std::min(e.from.crd.c, C_1);
|
||||
e.from.crd.c = std::max(e.from.crd.c, 0l);
|
||||
|
||||
e.to.crd.r = std::min(e.to.crd.r, R);
|
||||
e.to.crd.r = std::max(e.to.crd.r, 0l);
|
||||
e.to.crd.c = std::min(e.to.crd.c, C);
|
||||
e.to.crd.c = std::max(e.to.crd.c, 0l);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit Grid(const Rst &rst, const Coord &cellsz, const Coord &overlap)
|
||||
: m_rst{&rst}
|
||||
|
|
@ -319,8 +333,8 @@ public:
|
|||
, m_res_1{m_cellsize.r - 1, m_cellsize.c - 1}
|
||||
, m_window{overlap.r < cellsz.r ? cellsz.r - overlap.r : cellsz.r,
|
||||
overlap.c < cellsz.c ? cellsz.c - overlap.c : cellsz.c}
|
||||
, m_gridsize{(rows(rst) - overlap.r) / m_window.r,
|
||||
(cols(rst) - overlap.c) / m_window.c}
|
||||
, m_gridsize{2 + (long(rows(rst)) - overlap.r) / m_window.r,
|
||||
2 + (long(cols(rst)) - overlap.c) / m_window.c}
|
||||
, m_tags(m_gridsize.r * m_gridsize.c, 0)
|
||||
{}
|
||||
|
||||
|
|
@ -350,7 +364,7 @@ public:
|
|||
Dir prev = Dir::none, next = next_dir(prev, get_tag(idx));
|
||||
|
||||
while (next != Dir::none && !is_visited(idx, prev)) {
|
||||
Coord ringvertex{idx, size_t(next)};
|
||||
Coord ringvertex{long(idx), long(next)};
|
||||
ring.emplace_back(ringvertex);
|
||||
set_visited(idx, prev);
|
||||
|
||||
|
|
@ -379,9 +393,11 @@ public:
|
|||
TRasterValue<Rst> isov)
|
||||
{
|
||||
for_each(std::forward<ExecutionPolicy>(policy),
|
||||
rings.begin(), rings.end(), [this, isov] (Ring &ring, size_t) {
|
||||
rings.begin(), rings.end(), [this, isov] (Ring &ring, size_t)
|
||||
{
|
||||
for (Coord &ringvertex : ring) {
|
||||
Edge e = edge(ringvertex);
|
||||
|
||||
CellIt found = std::lower_bound(e.from, e.to, isov);
|
||||
ringvertex = found.crd;
|
||||
}
|
||||
|
|
@ -401,7 +417,7 @@ std::vector<marchsq::Ring> execute_with_policy(ExecutionPolicy && policy,
|
|||
|
||||
if (!windowsize.r) windowsize.r = 2;
|
||||
if (!windowsize.c)
|
||||
windowsize.c = std::max(size_t(2), windowsize.r * ratio);
|
||||
windowsize.c = std::max(2l, long(windowsize.r * ratio));
|
||||
|
||||
Coord overlap{1};
|
||||
|
||||
|
|
|
|||
|
|
@ -33,15 +33,15 @@ template<class Fn> void foreach_vertex(ExPolygon &poly, Fn &&fn)
|
|||
for (auto &p : h.points) fn(p);
|
||||
}
|
||||
|
||||
ExPolygons raster_to_polygons(const RasterGrayscaleAA &rst, float accuracy)
|
||||
ExPolygons raster_to_polygons(const RasterGrayscaleAA &rst, Vec2i windowsize)
|
||||
{
|
||||
size_t rows = rst.resolution().height_px, cols = rst.resolution().width_px;
|
||||
|
||||
if (rows < 2 || cols < 2) return {};
|
||||
|
||||
Polygons polys;
|
||||
size_t w_rows = (2 + rows / 8) - size_t(accuracy * rows / 8);
|
||||
size_t w_cols = std::max(size_t(2), w_rows * cols / rows);
|
||||
long w_rows = std::max(2l, long(windowsize.y()));
|
||||
long w_cols = std::max(2l, long(windowsize.x()));
|
||||
|
||||
std::vector<marchsq::Ring> rings =
|
||||
marchsq::execute(rst, 128, {w_rows, w_cols});
|
||||
|
|
@ -49,6 +49,9 @@ ExPolygons raster_to_polygons(const RasterGrayscaleAA &rst, float accuracy)
|
|||
polys.reserve(rings.size());
|
||||
|
||||
auto pxd = rst.pixel_dimensions();
|
||||
pxd.w_mm = (rst.resolution().width_px * pxd.w_mm) / (rst.resolution().width_px - 1);
|
||||
pxd.h_mm = (rst.resolution().height_px * pxd.h_mm) / (rst.resolution().height_px - 1);
|
||||
|
||||
for (const marchsq::Ring &ring : rings) {
|
||||
Polygon poly; Points &pts = poly.points;
|
||||
pts.reserve(ring.size());
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ namespace sla {
|
|||
|
||||
class RasterGrayscaleAA;
|
||||
|
||||
ExPolygons raster_to_polygons(const RasterGrayscaleAA &rst, float accuracy = 1.f);
|
||||
ExPolygons raster_to_polygons(const RasterGrayscaleAA &rst, Vec2i windowsize = {2, 2});
|
||||
|
||||
}}
|
||||
}} // namespace Slic3r::sla
|
||||
|
||||
#endif // RASTERTOPOLYGONS_HPP
|
||||
|
|
|
|||
|
|
@ -1,23 +1,40 @@
|
|||
|
||||
#include "SlicesToTriangleMesh.hpp"
|
||||
|
||||
#include "libslic3r/TriangulateWall.hpp"
|
||||
#include "libslic3r/MTUtils.hpp"
|
||||
#include "libslic3r/SLA/Contour3D.hpp"
|
||||
#include "libslic3r/ClipperUtils.hpp"
|
||||
#include "libslic3r/Tesselate.hpp"
|
||||
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/parallel_reduce.h>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
inline sla::Contour3D walls(const Polygon &lower,
|
||||
const Polygon &upper,
|
||||
double lower_z_mm,
|
||||
double upper_z_mm)
|
||||
inline sla::Contour3D wall_strip(const Polygon &poly,
|
||||
double lower_z_mm,
|
||||
double upper_z_mm)
|
||||
{
|
||||
Wall w = triangulate_wall(lower, upper, lower_z_mm, upper_z_mm);
|
||||
|
||||
sla::Contour3D ret;
|
||||
ret.points = std::move(w.first);
|
||||
ret.faces3 = std::move(w.second);
|
||||
|
||||
size_t startidx = ret.points.size();
|
||||
size_t offs = poly.points.size();
|
||||
|
||||
ret.points.reserve(ret.points.size() + 2 *offs);
|
||||
|
||||
for (const Point &p : poly.points)
|
||||
ret.points.emplace_back(to_3d(unscaled(p), lower_z_mm));
|
||||
|
||||
for (const Point &p : poly.points)
|
||||
ret.points.emplace_back(to_3d(unscaled(p), upper_z_mm));
|
||||
|
||||
for (size_t i = startidx + 1; i < startidx + offs; ++i) {
|
||||
ret.faces3.emplace_back(i - 1, i, i + offs - 1);
|
||||
ret.faces3.emplace_back(i, i + offs, i + offs - 1);
|
||||
}
|
||||
|
||||
ret.faces3.emplace_back(startidx + offs - 1, startidx, startidx + 2 * offs - 1);
|
||||
ret.faces3.emplace_back(startidx, startidx + offs, startidx + 2 * offs - 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -27,7 +44,7 @@ sla::Contour3D inline straight_walls(const Polygon &plate,
|
|||
double lo_z,
|
||||
double hi_z)
|
||||
{
|
||||
return walls(plate, plate, lo_z, hi_z);
|
||||
return wall_strip(plate, lo_z, hi_z);
|
||||
}
|
||||
|
||||
sla::Contour3D inline straight_walls(const ExPolygon &plate,
|
||||
|
|
@ -43,7 +60,7 @@ sla::Contour3D inline straight_walls(const ExPolygon &plate,
|
|||
sla::Contour3D inline straight_walls(const ExPolygons &slice,
|
||||
double lo_z,
|
||||
double hi_z)
|
||||
{
|
||||
{
|
||||
sla::Contour3D ret;
|
||||
for (const ExPolygon &poly : slice)
|
||||
ret.merge(straight_walls(poly, lo_z, hi_z));
|
||||
|
|
@ -51,32 +68,60 @@ sla::Contour3D inline straight_walls(const ExPolygons &slice,
|
|||
return ret;
|
||||
}
|
||||
|
||||
sla::Contour3D slices_to_triangle_mesh(const std::vector<ExPolygons> &slices,
|
||||
double zmin,
|
||||
const std::vector<float> & grid)
|
||||
{
|
||||
assert(slices.size() == grid.size());
|
||||
|
||||
using Layers = std::vector<sla::Contour3D>;
|
||||
std::vector<sla::Contour3D> layers(slices.size());
|
||||
size_t len = slices.size() - 1;
|
||||
|
||||
tbb::parallel_for(size_t(0), len, [&slices, &layers, &grid](size_t i) {
|
||||
const ExPolygons &upper = slices[i + 1];
|
||||
const ExPolygons &lower = slices[i];
|
||||
|
||||
ExPolygons dff1 = diff_ex(lower, upper);
|
||||
ExPolygons dff2 = diff_ex(upper, lower);
|
||||
layers[i].merge(triangulate_expolygons_3d(dff1, grid[i], NORMALS_UP));
|
||||
layers[i].merge(triangulate_expolygons_3d(dff2, grid[i], NORMALS_DOWN));
|
||||
layers[i].merge(straight_walls(upper, grid[i], grid[i + 1]));
|
||||
|
||||
});
|
||||
|
||||
sla::Contour3D ret = tbb::parallel_reduce(
|
||||
tbb::blocked_range(layers.begin(), layers.end()),
|
||||
sla::Contour3D{},
|
||||
[](const tbb::blocked_range<Layers::iterator>& r, sla::Contour3D init) {
|
||||
for(auto it = r.begin(); it != r.end(); ++it ) init.merge(*it);
|
||||
return init;
|
||||
},
|
||||
[]( const sla::Contour3D &a, const sla::Contour3D &b ) {
|
||||
sla::Contour3D res{a}; res.merge(b); return res;
|
||||
});
|
||||
|
||||
ret.merge(triangulate_expolygons_3d(slices.front(), zmin, NORMALS_DOWN));
|
||||
ret.merge(straight_walls(slices.front(), zmin, grid.front()));
|
||||
ret.merge(triangulate_expolygons_3d(slices.back(), grid.back(), NORMALS_UP));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void slices_to_triangle_mesh(TriangleMesh & mesh,
|
||||
const std::vector<ExPolygons> &slices,
|
||||
double zmin,
|
||||
double lh,
|
||||
double ilh)
|
||||
{
|
||||
sla::Contour3D cntr3d;
|
||||
double h = zmin;
|
||||
std::vector<sla::Contour3D> wall_meshes(slices.size());
|
||||
std::vector<float> grid(slices.size(), zmin + ilh);
|
||||
|
||||
auto it = slices.begin(), xt = std::next(it);
|
||||
cntr3d.merge(triangulate_expolygons_3d(*it, h, NORMALS_DOWN));
|
||||
cntr3d.merge(straight_walls(*it, h, h + ilh));
|
||||
h += ilh;
|
||||
while (xt != slices.end()) {
|
||||
ExPolygons dff1 = diff_ex(*it, *xt);
|
||||
ExPolygons dff2 = diff_ex(*xt, *it);
|
||||
cntr3d.merge(triangulate_expolygons_3d(dff1, h, NORMALS_UP));
|
||||
cntr3d.merge(triangulate_expolygons_3d(dff2, h, NORMALS_UP));
|
||||
cntr3d.merge(straight_walls(*xt, h, h + lh));
|
||||
h += lh;
|
||||
++it; ++xt;
|
||||
}
|
||||
for (size_t i = 1; i < grid.size(); ++i) grid[i] = grid[i - 1] + lh;
|
||||
|
||||
cntr3d.merge(triangulate_expolygons_3d(*it, h, NORMALS_UP));
|
||||
|
||||
mesh.merge(sla::to_triangle_mesh(cntr3d));
|
||||
sla::Contour3D cntr = slices_to_triangle_mesh(slices, zmin, grid);
|
||||
mesh.merge(sla::to_triangle_mesh(cntr));
|
||||
mesh.repaired = true;
|
||||
mesh.require_shared_vertices();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,90 +17,14 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
class Zipper::Impl {
|
||||
class Zipper::Impl: public MZ_Archive {
|
||||
public:
|
||||
mz_zip_archive arch;
|
||||
std::string m_zipname;
|
||||
|
||||
static std::string get_errorstr(mz_zip_error mz_err)
|
||||
{
|
||||
switch (mz_err)
|
||||
{
|
||||
case MZ_ZIP_NO_ERROR:
|
||||
return "no error";
|
||||
case MZ_ZIP_UNDEFINED_ERROR:
|
||||
return L("undefined error");
|
||||
case MZ_ZIP_TOO_MANY_FILES:
|
||||
return L("too many files");
|
||||
case MZ_ZIP_FILE_TOO_LARGE:
|
||||
return L("file too large");
|
||||
case MZ_ZIP_UNSUPPORTED_METHOD:
|
||||
return L("unsupported method");
|
||||
case MZ_ZIP_UNSUPPORTED_ENCRYPTION:
|
||||
return L("unsupported encryption");
|
||||
case MZ_ZIP_UNSUPPORTED_FEATURE:
|
||||
return L("unsupported feature");
|
||||
case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR:
|
||||
return L("failed finding central directory");
|
||||
case MZ_ZIP_NOT_AN_ARCHIVE:
|
||||
return L("not a ZIP archive");
|
||||
case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED:
|
||||
return L("invalid header or archive is corrupted");
|
||||
case MZ_ZIP_UNSUPPORTED_MULTIDISK:
|
||||
return L("unsupported multidisk archive");
|
||||
case MZ_ZIP_DECOMPRESSION_FAILED:
|
||||
return L("decompression failed or archive is corrupted");
|
||||
case MZ_ZIP_COMPRESSION_FAILED:
|
||||
return L("compression failed");
|
||||
case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE:
|
||||
return L("unexpected decompressed size");
|
||||
case MZ_ZIP_CRC_CHECK_FAILED:
|
||||
return L("CRC-32 check failed");
|
||||
case MZ_ZIP_UNSUPPORTED_CDIR_SIZE:
|
||||
return L("unsupported central directory size");
|
||||
case MZ_ZIP_ALLOC_FAILED:
|
||||
return L("allocation failed");
|
||||
case MZ_ZIP_FILE_OPEN_FAILED:
|
||||
return L("file open failed");
|
||||
case MZ_ZIP_FILE_CREATE_FAILED:
|
||||
return L("file create failed");
|
||||
case MZ_ZIP_FILE_WRITE_FAILED:
|
||||
return L("file write failed");
|
||||
case MZ_ZIP_FILE_READ_FAILED:
|
||||
return L("file read failed");
|
||||
case MZ_ZIP_FILE_CLOSE_FAILED:
|
||||
return L("file close failed");
|
||||
case MZ_ZIP_FILE_SEEK_FAILED:
|
||||
return L("file seek failed");
|
||||
case MZ_ZIP_FILE_STAT_FAILED:
|
||||
return L("file stat failed");
|
||||
case MZ_ZIP_INVALID_PARAMETER:
|
||||
return L("invalid parameter");
|
||||
case MZ_ZIP_INVALID_FILENAME:
|
||||
return L("invalid filename");
|
||||
case MZ_ZIP_BUF_TOO_SMALL:
|
||||
return L("buffer too small");
|
||||
case MZ_ZIP_INTERNAL_ERROR:
|
||||
return L("internal error");
|
||||
case MZ_ZIP_FILE_NOT_FOUND:
|
||||
return L("file not found");
|
||||
case MZ_ZIP_ARCHIVE_TOO_LARGE:
|
||||
return L("archive is too large");
|
||||
case MZ_ZIP_VALIDATION_FAILED:
|
||||
return L("validation failed");
|
||||
case MZ_ZIP_WRITE_CALLBACK_FAILED:
|
||||
return L("write calledback failed");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return "unknown error";
|
||||
}
|
||||
|
||||
std::string formatted_errorstr() const
|
||||
{
|
||||
return L("Error with zip archive") + " " + m_zipname + ": " +
|
||||
get_errorstr(arch.m_last_error) + "!";
|
||||
get_errorstr() + "!";
|
||||
}
|
||||
|
||||
SLIC3R_NORETURN void blow_up() const
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ 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);
|
||||
e_compression level = FAST_COMPRESSION);
|
||||
~Zipper();
|
||||
|
||||
// No copies allwed, this is a file resource...
|
||||
|
|
|
|||
|
|
@ -1,9 +1,17 @@
|
|||
#include <exception>
|
||||
|
||||
#include "miniz_extension.hpp"
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MINGW64__)
|
||||
#include "boost/nowide/cstdio.hpp"
|
||||
#endif
|
||||
|
||||
#include "I18N.hpp"
|
||||
|
||||
//! macro used to mark string used at localization,
|
||||
//! return same string
|
||||
#define L(s) Slic3r::I18N::translate(s)
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace {
|
||||
|
|
@ -68,4 +76,84 @@ bool open_zip_writer(mz_zip_archive *zip, const std::string &fname)
|
|||
bool close_zip_reader(mz_zip_archive *zip) { return close_zip(zip, true); }
|
||||
bool close_zip_writer(mz_zip_archive *zip) { return close_zip(zip, false); }
|
||||
|
||||
MZ_Archive::MZ_Archive()
|
||||
{
|
||||
mz_zip_zero_struct(&arch);
|
||||
}
|
||||
|
||||
std::string MZ_Archive::get_errorstr(mz_zip_error mz_err)
|
||||
{
|
||||
switch (mz_err)
|
||||
{
|
||||
case MZ_ZIP_NO_ERROR:
|
||||
return "no error";
|
||||
case MZ_ZIP_UNDEFINED_ERROR:
|
||||
return L("undefined error");
|
||||
case MZ_ZIP_TOO_MANY_FILES:
|
||||
return L("too many files");
|
||||
case MZ_ZIP_FILE_TOO_LARGE:
|
||||
return L("file too large");
|
||||
case MZ_ZIP_UNSUPPORTED_METHOD:
|
||||
return L("unsupported method");
|
||||
case MZ_ZIP_UNSUPPORTED_ENCRYPTION:
|
||||
return L("unsupported encryption");
|
||||
case MZ_ZIP_UNSUPPORTED_FEATURE:
|
||||
return L("unsupported feature");
|
||||
case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR:
|
||||
return L("failed finding central directory");
|
||||
case MZ_ZIP_NOT_AN_ARCHIVE:
|
||||
return L("not a ZIP archive");
|
||||
case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED:
|
||||
return L("invalid header or archive is corrupted");
|
||||
case MZ_ZIP_UNSUPPORTED_MULTIDISK:
|
||||
return L("unsupported multidisk archive");
|
||||
case MZ_ZIP_DECOMPRESSION_FAILED:
|
||||
return L("decompression failed or archive is corrupted");
|
||||
case MZ_ZIP_COMPRESSION_FAILED:
|
||||
return L("compression failed");
|
||||
case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE:
|
||||
return L("unexpected decompressed size");
|
||||
case MZ_ZIP_CRC_CHECK_FAILED:
|
||||
return L("CRC-32 check failed");
|
||||
case MZ_ZIP_UNSUPPORTED_CDIR_SIZE:
|
||||
return L("unsupported central directory size");
|
||||
case MZ_ZIP_ALLOC_FAILED:
|
||||
return L("allocation failed");
|
||||
case MZ_ZIP_FILE_OPEN_FAILED:
|
||||
return L("file open failed");
|
||||
case MZ_ZIP_FILE_CREATE_FAILED:
|
||||
return L("file create failed");
|
||||
case MZ_ZIP_FILE_WRITE_FAILED:
|
||||
return L("file write failed");
|
||||
case MZ_ZIP_FILE_READ_FAILED:
|
||||
return L("file read failed");
|
||||
case MZ_ZIP_FILE_CLOSE_FAILED:
|
||||
return L("file close failed");
|
||||
case MZ_ZIP_FILE_SEEK_FAILED:
|
||||
return L("file seek failed");
|
||||
case MZ_ZIP_FILE_STAT_FAILED:
|
||||
return L("file stat failed");
|
||||
case MZ_ZIP_INVALID_PARAMETER:
|
||||
return L("invalid parameter");
|
||||
case MZ_ZIP_INVALID_FILENAME:
|
||||
return L("invalid filename");
|
||||
case MZ_ZIP_BUF_TOO_SMALL:
|
||||
return L("buffer too small");
|
||||
case MZ_ZIP_INTERNAL_ERROR:
|
||||
return L("internal error");
|
||||
case MZ_ZIP_FILE_NOT_FOUND:
|
||||
return L("file not found");
|
||||
case MZ_ZIP_ARCHIVE_TOO_LARGE:
|
||||
return L("archive is too large");
|
||||
case MZ_ZIP_VALIDATION_FAILED:
|
||||
return L("validation failed");
|
||||
case MZ_ZIP_WRITE_CALLBACK_FAILED:
|
||||
return L("write calledback failed");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return "unknown error";
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
|||
|
|
@ -11,6 +11,25 @@ bool open_zip_writer(mz_zip_archive *zip, const std::string &fname_utf8);
|
|||
bool close_zip_reader(mz_zip_archive *zip);
|
||||
bool close_zip_writer(mz_zip_archive *zip);
|
||||
|
||||
}
|
||||
class MZ_Archive {
|
||||
public:
|
||||
mz_zip_archive arch;
|
||||
|
||||
MZ_Archive();
|
||||
|
||||
static std::string get_errorstr(mz_zip_error mz_err);
|
||||
|
||||
std::string get_errorstr() const
|
||||
{
|
||||
return get_errorstr(arch.m_last_error) + "!";
|
||||
}
|
||||
|
||||
bool is_alive() const
|
||||
{
|
||||
return arch.m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // MINIZ_EXTENSION_HPP
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue