diff --git a/resources/icons/white/colorchange_add_m.svg b/resources/icons/white/colorchange_add_m.svg new file mode 100644 index 0000000000..2266560daa --- /dev/null +++ b/resources/icons/white/colorchange_add_m.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + diff --git a/resources/icons/white/edit_gcode.svg b/resources/icons/white/edit_gcode.svg new file mode 100644 index 0000000000..85836c0b49 --- /dev/null +++ b/resources/icons/white/edit_gcode.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + diff --git a/resources/icons/white/error_tick.svg b/resources/icons/white/error_tick.svg new file mode 100644 index 0000000000..f3de981f03 --- /dev/null +++ b/resources/icons/white/error_tick.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/resources/icons/white/pause_print.svg b/resources/icons/white/pause_print.svg new file mode 100644 index 0000000000..73f747fffd --- /dev/null +++ b/resources/icons/white/pause_print.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + diff --git a/src/libslic3r/ExPolygon.cpp b/src/libslic3r/ExPolygon.cpp index 02cc126a38..f698a35589 100644 --- a/src/libslic3r/ExPolygon.cpp +++ b/src/libslic3r/ExPolygon.cpp @@ -132,8 +132,7 @@ ExPolygon::has_boundary_point(const Point &point) const return false; } -bool -ExPolygon::overlaps(const ExPolygon &other) const +bool ExPolygon::overlaps(const ExPolygon &other) const { #if 0 BoundingBox bbox = get_extents(other); @@ -150,6 +149,7 @@ ExPolygon::overlaps(const ExPolygon &other) const #endif if (! pl_out.empty()) return true; + //FIXME ExPolygon::overlaps() shall be commutative, it is not! return ! other.contour.points.empty() && this->contains_b(other.contour.points.front()); } diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index ba12a1edbb..ff9e439ba8 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -5,6 +5,7 @@ #include #include +#include namespace Slic3r { @@ -230,8 +231,128 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime return out; } +enum class FuzzyShape { + Triangle, + Sawtooth, + Random +}; + +static void fuzzy_polygon(Polygon &poly, FuzzyShape shape, double fuzzy_skin_thickness, double fuzzy_skin_point_dist) +{ +#if 0 + Point last = poly.points.at(poly.points.size() - 1); + Point last_processed = last; + + double max_length = scale_(2); + double min_length = scale_(1); + + if (poly.length() < scale_(5)) + return; + + deepness *= 3; + + bool triangle_or_sawtooth = shape == FuzzyShape::Sawtooth; + double length_sum = 0; + Points::iterator it = poly.points.begin(); + while (it != poly.points.end()) { + Point &pt = *it; + + Line line(last, pt); + double length = line.length(); + + // split long line + if (length > max_length) { + auto parts = int(ceil(length / max_length)); + if (parts == 2) { + Point point_to_insert(line.midpoint()); + it = poly.points.insert(it, point_to_insert); + } + else { + Vector part_vector = line.vector() / parts; + + Points points_to_insert; + Point point_to_insert(last); + while (--parts) { + point_to_insert += part_vector; + Point point_to_insert_2(point_to_insert); + points_to_insert.push_back(point_to_insert_2); + } + + it = poly.points.insert(it, points_to_insert.begin(), points_to_insert.end()); + } + continue; + } + + length_sum += length; + + // join short lines + if (length_sum < min_length) { + last = pt; + it = poly.points.erase(it); + continue; + } + + line = Line(last_processed, pt); + last = pt; + last_processed = pt; + + if (shape == FuzzyShape::Random) { + triangle_or_sawtooth = !(rand() % 2); + } + + Point point_to_insert(triangle_or_sawtooth ? pt : line.midpoint()); + + int scale = (rand() % deepness) + 1; + + Vec2d normal = line.normal().cast(); + normal /= line.length() / scale_(1.) / ((double)scale / 20.); + + it = poly.points.insert(it, point_to_insert + normal.cast()) + 2; + + length_sum = 0; + } + +#else + const double min_dist_between_points = fuzzy_skin_point_dist * 3. / 4.; // hardcoded: the point distance may vary between 3/4 and 5/4 the supplied value + const double range_random_point_dist = fuzzy_skin_point_dist / 2.; + double dist_left_over = double(rand()) * (min_dist_between_points / 2) / double(RAND_MAX); // the distance to be traversed on the line before making the first new point + Point* p0 = &poly.points.back(); + Points out; + out.reserve(poly.points.size()); + for (Point &p1 : poly.points) + { // 'a' is the (next) new point between p0 and p1 + Vec2d p0p1 = (p1 - *p0).cast(); + double p0p1_size = p0p1.norm(); + // so that p0p1_size - dist_last_point evaulates to dist_left_over - p0p1_size + double dist_last_point = dist_left_over + p0p1_size * 2.; + for (double p0pa_dist = dist_left_over; p0pa_dist < p0p1_size; + p0pa_dist += min_dist_between_points + double(rand()) * range_random_point_dist / double(RAND_MAX)) + { + double r = double(rand()) * (fuzzy_skin_thickness * 2.) / double(RAND_MAX) - fuzzy_skin_thickness; + out.emplace_back(*p0 + (p0p1 * (p0pa_dist / p0p1_size) + perp(p0p1).cast().normalized() * r).cast()); + dist_last_point = p0pa_dist; + } + dist_left_over = p0p1_size - dist_last_point; + p0 = &p1; + } + while (out.size() < 3) { + size_t point_idx = poly.size() - 2; + out.emplace_back(poly[point_idx]); + if (point_idx == 0) + break; + -- point_idx; + } + if (out.size() >= 3) + poly.points = std::move(out); +#endif +} + void PerimeterGenerator::process() { + // nasty hack! initialize random generator + auto time_us = std::chrono::duration_cast(std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()).time_since_epoch()).count(); + srand(this->layer_id * time_us); + // other perimeters m_mm3_per_mm = this->perimeter_flow.mm3_per_mm(); coord_t perimeter_width = this->perimeter_flow.scaled_width(); @@ -272,6 +393,32 @@ void PerimeterGenerator::process() m_lower_slices_polygons = offset(*this->lower_slices, float(scale_(+nozzle_diameter/2))); } + // fuzzy skin configuration + double fuzzy_skin_thickness; + double fuzzy_skin_point_dist; + FuzzyShape fuzzy_skin_shape; + if (this->object_config->fuzzy_skin_perimeter_mode != FuzzySkinPerimeterMode::None) { + switch (this->object_config->fuzzy_skin_shape) { + case FuzzySkinShape::Triangle1: + case FuzzySkinShape::Triangle2: + case FuzzySkinShape::Triangle3: + fuzzy_skin_shape = FuzzyShape::Triangle; + break; + case FuzzySkinShape::Sawtooth1: + case FuzzySkinShape::Sawtooth2: + case FuzzySkinShape::Sawtooth3: + fuzzy_skin_shape = FuzzyShape::Sawtooth; + break; + case FuzzySkinShape::Random1: + case FuzzySkinShape::Random2: + case FuzzySkinShape::Random3: + fuzzy_skin_shape = FuzzyShape::Random; + break; + } + fuzzy_skin_thickness = scale_(this->object_config->fuzzy_skin_thickness); + fuzzy_skin_point_dist = scale_(this->object_config->fuzzy_skin_point_dist); + } + // we need to process each island separately because we might have different // extra perimeters for each one for (const Surface &surface : this->slices->surfaces) { @@ -352,13 +499,35 @@ void PerimeterGenerator::process() // If i > loop_number, we were looking just for gaps. break; } - for (const ExPolygon &expolygon : offsets) { + for (ExPolygon &expolygon : offsets) { // Outer contour may overlap with an inner contour, // inner contour may overlap with another inner contour, // outer contour may overlap with itself. //FIXME evaluate the overlaps, annotate each point with an overlap depth, - // compensate for the depth of intersection. - contours[i].emplace_back(PerimeterGeneratorLoop(expolygon.contour, i, true)); + + bool skip_polygon = false; + + if (this->object_config->fuzzy_skin_perimeter_mode != FuzzySkinPerimeterMode::None) { + if (i == 0 && (this->object_config->fuzzy_skin_perimeter_mode != FuzzySkinPerimeterMode::ExternalSkipFirst || this->layer_id > 0)) { + if ( + this->object_config->fuzzy_skin_perimeter_mode == FuzzySkinPerimeterMode::External || + this->object_config->fuzzy_skin_perimeter_mode == FuzzySkinPerimeterMode::ExternalSkipFirst + ) { + ExPolygon expolygon_fuzzy(expolygon); + fuzzy_polygon(expolygon_fuzzy.contour, fuzzy_skin_shape, fuzzy_skin_thickness, fuzzy_skin_point_dist); + // compensate for the depth of intersection. + contours[i].emplace_back(PerimeterGeneratorLoop(expolygon_fuzzy.contour, i, true)); + skip_polygon = true; + } else + fuzzy_polygon(expolygon.contour, fuzzy_skin_shape, fuzzy_skin_thickness, fuzzy_skin_point_dist); + } + } + + if (!skip_polygon) { + // compensate for the depth of intersection. + contours[i].emplace_back(PerimeterGeneratorLoop(expolygon.contour, i, true)); + } + if (! expolygon.holes.empty()) { holes[i].reserve(holes[i].size() + expolygon.holes.size()); for (const Polygon &hole : expolygon.holes) diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index c24033df20..f75f653ef3 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -411,6 +411,7 @@ const std::vector& Preset::print_options() "solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first", "ironing", "ironing_type", "ironing_flowrate", "ironing_speed", "ironing_spacing", "max_print_speed", "max_volumetric_speed", "avoid_crossing_perimeters_max_detour", + "fuzzy_skin_perimeter_mode", "fuzzy_skin_shape", "fuzzy_skin_thickness", "fuzzy_skin_point_dist", #ifdef HAS_PRESSURE_EQUALIZER "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative", #endif /* HAS_PRESSURE_EQUALIZER */ diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index da2b655689..9247e69da3 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1007,6 +1007,68 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; def->set_default_value(new ConfigOptionInts { 0 }); + def = this->add("fuzzy_skin_perimeter_mode", coEnum); + def->label = L("Fuzzy skin perimeter mode"); + def->category = L("Fuzzy Skin"); + def->tooltip = L("Fuzzy skin perimeter mode."); + + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.push_back("none"); + def->enum_values.push_back("external_only"); + def->enum_values.push_back("external_only_skip_first_layer"); + def->enum_values.push_back("all"); + def->enum_labels.push_back(L("None")); + def->enum_labels.push_back(L("External")); + def->enum_labels.push_back(L("External (skip first layer)")); + def->enum_labels.push_back(L("All perimeters")); + def->mode = comSimple; + def->set_default_value(new ConfigOptionEnum(FuzzySkinPerimeterMode::None)); + + def = this->add("fuzzy_skin_shape", coEnum); + def->label = L("Fuzzy skin shape"); + def->category = L("Fuzzy Skin"); + def->tooltip = L("Fuzzy skin shape."); + + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.push_back("triangle1"); + def->enum_values.push_back("triangle2"); + def->enum_values.push_back("triangle3"); + def->enum_values.push_back("sawtooth1"); + def->enum_values.push_back("sawtooth2"); + def->enum_values.push_back("sawtooth3"); + def->enum_values.push_back("random1"); + def->enum_values.push_back("random2"); + def->enum_values.push_back("random3"); + def->enum_labels.push_back(L("Triangle (1)")); + def->enum_labels.push_back(L("Triangle (2)")); + def->enum_labels.push_back(L("Triangle (3)")); + def->enum_labels.push_back(L("Sawtooth (1)")); + def->enum_labels.push_back(L("Sawtooth (2)")); + def->enum_labels.push_back(L("Sawtooth (3)")); + def->enum_labels.push_back(L("Random (1)")); + def->enum_labels.push_back(L("Random (2)")); + def->enum_labels.push_back(L("Random (3)")); + def->mode = comSimple; + def->set_default_value(new ConfigOptionEnum(FuzzySkinShape::Triangle1)); + + def = this->add("fuzzy_skin_thickness", coFloat); + def->label = L("Fuzzy skin thickness"); + def->category = L("Fuzzy Skin"); + def->tooltip = L(""); + def->sidetext = L("mm"); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(0.3)); + + def = this->add("fuzzy_skin_point_dist", coFloat); + def->label = L("Fuzzy skin point distance"); + def->category = L("Fuzzy Skin"); + def->tooltip = L(""); + def->sidetext = L("mm"); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(0.8)); + def = this->add("gap_fill_speed", coFloat); def->label = L("Gap fill"); def->category = L("Speed"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index fa09cfb172..40929c34b0 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -43,6 +43,25 @@ enum AuthorizationType { atKeyPassword, atUserPassword }; +enum class FuzzySkinPerimeterMode { + None, + External, + ExternalSkipFirst, + All +}; + +enum class FuzzySkinShape { + Triangle1, + Triangle2, + Triangle3, + Sawtooth1, + Sawtooth2, + Sawtooth3, + Random1, + Random2, + Random3 +}; + enum InfillPattern : int { ipRectilinear, ipMonotonic, ipAlignedRectilinear, ipGrid, ipTriangles, ipStars, ipCubic, ipLine, ipConcentric, ipHoneycomb, ip3DHoneycomb, ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipAdaptiveCubic, ipSupportCubic, ipCount, @@ -140,6 +159,33 @@ template<> inline const t_config_enum_values& ConfigOptionEnum inline const t_config_enum_values& ConfigOptionEnum::get_enum_values() { + static t_config_enum_values keys_map; + if (keys_map.empty()) { + keys_map["none"] = int(FuzzySkinPerimeterMode::None); + keys_map["external_only"] = int(FuzzySkinPerimeterMode::External); + keys_map["external_only_skip_first_layer"] = int(FuzzySkinPerimeterMode::ExternalSkipFirst); + keys_map["all"] = int(FuzzySkinPerimeterMode::All); + } + return keys_map; +} + +template<> inline const t_config_enum_values& ConfigOptionEnum::get_enum_values() { + static t_config_enum_values keys_map; + if (keys_map.empty()) { + keys_map["triangle1"] = int(FuzzySkinShape::Triangle1); + keys_map["triangle2"] = int(FuzzySkinShape::Triangle2); + keys_map["triangle3"] = int(FuzzySkinShape::Triangle3); + keys_map["sawtooth1"] = int(FuzzySkinShape::Sawtooth1); + keys_map["sawtooth2"] = int(FuzzySkinShape::Sawtooth2); + keys_map["sawtooth3"] = int(FuzzySkinShape::Sawtooth3); + keys_map["random1"] = int(FuzzySkinShape::Random1); + keys_map["random2"] = int(FuzzySkinShape::Random2); + keys_map["random3"] = int(FuzzySkinShape::Random3); + } + return keys_map; +} + template<> inline const t_config_enum_values& ConfigOptionEnum::get_enum_values() { static t_config_enum_values keys_map; if (keys_map.empty()) { @@ -432,6 +478,10 @@ public: ConfigOptionFloat elefant_foot_compensation; ConfigOptionFloatOrPercent extrusion_width; ConfigOptionFloatOrPercent first_layer_height; + ConfigOptionEnum fuzzy_skin_perimeter_mode; + ConfigOptionEnum fuzzy_skin_shape; + ConfigOptionFloat fuzzy_skin_thickness; + ConfigOptionFloat fuzzy_skin_point_dist; ConfigOptionBool infill_only_where_needed; // Force the generation of solid shells between adjacent materials/volumes. ConfigOptionBool interface_shells; @@ -477,6 +527,10 @@ protected: OPT_PTR(elefant_foot_compensation); OPT_PTR(extrusion_width); OPT_PTR(first_layer_height); + OPT_PTR(fuzzy_skin_perimeter_mode); + OPT_PTR(fuzzy_skin_shape); + OPT_PTR(fuzzy_skin_thickness); + OPT_PTR(fuzzy_skin_point_dist); OPT_PTR(infill_only_where_needed); OPT_PTR(interface_shells); OPT_PTR(layer_height); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 99b4130f4c..dcf94fe9ab 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -521,6 +521,10 @@ bool PrintObject::invalidate_state_by_config_options(const std::vectorbbox.overlap(rhs.bbox) && (this->polygon->overlaps(*rhs.polygon) || rhs.polygon->overlaps(*this->polygon)); } float overlap_area(const Structure &rhs) const { diff --git a/src/miniz/README-Prusa.txt b/src/miniz/README-Prusa.txt new file mode 100644 index 0000000000..7ed99c5347 --- /dev/null +++ b/src/miniz/README-Prusa.txt @@ -0,0 +1,27 @@ +This library is based on miniz 2.1.0 - amalgamated version. + +---------------------------------------------------------------- + +Merged with https://github.com/richgel999/miniz/pull/147 +to support writing a zipped file using a callback without +knowing the size of the file up front. + +Vojtech made the following comments to the pull request above: + +The pull request looks good to me in general. We need such a functionality at https://github.com/prusa3d/PrusaSlicer so we are going to merge it into our project. Namely, we are exporting potentially huge model files, which are XML encoded, thus the compression ration is quite high and keeping the XML encoded model file in memory is not really practical. + +I am a bit uneasy about two things though: + +mz_zip_writer_create_zip64_extra_data() call at the start of the file block stores uncompressed and compressed size. Naturally the uncompressed size will be over estimated, while the compressed size will be zero (as it was before). I suppose it does not make any difference, as usually the decompressors do not read this block, but they rely on the copy of this block in the central directory at the end of the ZIP file. I used https://en.wikipedia.org/wiki/ZIP_(file_format) as a source and there is no definition of the ZIP64 extra data block, though the "Data descriptor" section says: +If the bit at offset 3 (0x08) of the general-purpose flags field is set, then the CRC-32 and file sizes are not known when the header is written. The fields in the local header are filled with zero, and the CRC-32 and size are appended in a 12-byte structure (optionally preceded by a 4-byte signature) immediately after the compressed data: + +Thus I suppose it is all right if the file size at the start of the file block is not correct. + +There are weird conditions in the original code as if (uncomp_size <= 3), if (uncomp_size == 0). I am not quite sure what will happen if one called your modified mz_zip_writer_add_read_buf_callback() with maximum size >= 4, but the callback provided less than 4 bytes. This is not a problem in our application, but in general it could be an issue. + +Is it an issue if the maximum size mandates a 64bit format, while the callback provides less than 4GB of data? I suppose there will only be a tiny bit of performance and file size penalty, but the code will work and the exported ZIP file will be valid. + +Are you using your modification in a production code? How well is your modification tested? + +---------------------------------------------------------------- + diff --git a/src/miniz/miniz.c b/src/miniz/miniz.c index 9ded4c75ab..66afb94c21 100644 --- a/src/miniz/miniz.c +++ b/src/miniz/miniz.c @@ -6370,13 +6370,13 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n return MZ_TRUE; } -mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 size_to_add, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, +mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 max_size, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len) { mz_uint16 gen_flags = MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR; mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes; mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0; - mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = size_to_add, comp_size = 0; + mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, comp_size = 0; size_t archive_name_size; mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; mz_uint8 *pExtra_data = NULL; @@ -6398,7 +6398,7 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA pState = pZip->m_pState; - if ((!pState->m_zip64) && (uncomp_size > MZ_UINT32_MAX)) + if ((!pState->m_zip64) && (max_size > MZ_UINT32_MAX)) { /* Source file is too large for non-zip64 */ /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ @@ -6455,7 +6455,7 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA } #endif - if (uncomp_size <= 3) + if (max_size <= 3) level = 0; if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes)) @@ -6471,7 +6471,7 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA MZ_ASSERT((cur_archive_file_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } - if (uncomp_size && level) + if (max_size && level) { method = MZ_DEFLATED; } @@ -6479,11 +6479,11 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA MZ_CLEAR_OBJ(local_dir_header); if (pState->m_zip64) { - if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX) + if (max_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX) { pExtra_data = extra_data; - extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, - (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); + extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (max_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, + (max_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); } if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len), 0, 0, 0, method, gen_flags, dos_time, dos_date)) @@ -6534,9 +6534,8 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA cur_archive_file_ofs += user_extra_data_len; } - if (uncomp_size) + if (max_size) { - mz_uint64 uncomp_remaining = uncomp_size; void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE); if (!pRead_buf) { @@ -6545,19 +6544,27 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA if (!level) { - while (uncomp_remaining) + while (1) { - mz_uint n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining); - if ((read_callback(callback_opaque, file_ofs, pRead_buf, n) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n)) + size_t n = read_callback(callback_opaque, file_ofs, pRead_buf, MZ_ZIP_MAX_IO_BUF_SIZE); + if (n == 0) + break; + + if ((n > MZ_ZIP_MAX_IO_BUF_SIZE) || (file_ofs + n > max_size)) { pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); } - file_ofs += n; + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + } + file_ofs += n; uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n); - uncomp_remaining -= n; cur_archive_file_ofs += n; } + uncomp_size = file_ofs; comp_size = uncomp_size; } else @@ -6584,24 +6591,26 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA for (;;) { - size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE); tdefl_status status; tdefl_flush flush = TDEFL_NO_FLUSH; - if (read_callback(callback_opaque, file_ofs, pRead_buf, in_buf_size)!= in_buf_size) + size_t n = read_callback(callback_opaque, file_ofs, pRead_buf, MZ_ZIP_MAX_IO_BUF_SIZE); + if ((n > MZ_ZIP_MAX_IO_BUF_SIZE) || (file_ofs + n > max_size)) { mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); break; } - file_ofs += in_buf_size; - uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size); - uncomp_remaining -= in_buf_size; + file_ofs += n; + uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n); if (pZip->m_pNeeds_keepalive != NULL && pZip->m_pNeeds_keepalive(pZip->m_pIO_opaque)) flush = TDEFL_FULL_FLUSH; - status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? flush : TDEFL_FINISH); + if (n == 0) + flush = TDEFL_FINISH; + + status = tdefl_compress_buffer(pComp, pRead_buf, n, flush); if (status == TDEFL_STATUS_DONE) { result = MZ_TRUE; @@ -6622,6 +6631,7 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA return MZ_FALSE; } + uncomp_size = file_ofs; comp_size = state.m_comp_size; cur_archive_file_ofs = state.m_cur_archive_file_ofs; } diff --git a/src/miniz/miniz.h b/src/miniz/miniz.h index 7db62811e5..63e5267872 100644 --- a/src/miniz/miniz.h +++ b/src/miniz/miniz.h @@ -1282,7 +1282,7 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n /* Adds the contents of a file to an archive. This function also records the disk file's modified time into the archive. */ /* File data is supplied via a read callback function. User mz_zip_writer_add_(c)file to add a file directly.*/ -mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 size_to_add, +mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 max_size, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, const char *user_extra_data_local, mz_uint user_extra_data_local_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len); diff --git a/src/slic3r/GUI/DoubleSlider.cpp b/src/slic3r/GUI/DoubleSlider.cpp index 8a2257274e..7ee5579e7c 100644 --- a/src/slic3r/GUI/DoubleSlider.cpp +++ b/src/slic3r/GUI/DoubleSlider.cpp @@ -160,6 +160,26 @@ void Control::msw_rescale() GetParent()->Layout(); } +void Control::sys_color_changed() +{ + m_bmp_add_tick_on .msw_rescale(); + m_bmp_add_tick_off.msw_rescale(); + m_bmp_del_tick_on .msw_rescale(); + m_bmp_del_tick_off.msw_rescale(); + m_tick_icon_dim = m_bmp_add_tick_on.GetBmpWidth(); + + m_bmp_one_layer_lock_on .msw_rescale(); + m_bmp_one_layer_lock_off .msw_rescale(); + m_bmp_one_layer_unlock_on .msw_rescale(); + m_bmp_one_layer_unlock_off.msw_rescale(); + m_lock_icon_dim = m_bmp_one_layer_lock_on.GetBmpWidth(); + + m_bmp_revert.msw_rescale(); + m_revert_icon_dim = m_bmp_revert.GetBmpWidth(); + m_bmp_cog.msw_rescale(); + m_cog_icon_dim = m_bmp_cog.GetBmpWidth(); +} + int Control::GetActiveValue() const { return m_selection == ssLower ? diff --git a/src/slic3r/GUI/DoubleSlider.hpp b/src/slic3r/GUI/DoubleSlider.hpp index 56baef6cf2..0d90367c0a 100644 --- a/src/slic3r/GUI/DoubleSlider.hpp +++ b/src/slic3r/GUI/DoubleSlider.hpp @@ -192,6 +192,7 @@ public: ~Control() {} void msw_rescale(); + void sys_color_changed(); int GetMinValue() const { return m_min_value; } int GetMaxValue() const { return m_max_value; } diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 360a5e5326..93e259e6a2 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -1200,6 +1200,10 @@ boost::any& Choice::get_value() } else if (m_opt_id.compare("ironing_type") == 0) m_value = static_cast(ret_enum); + else if (m_opt_id.compare("fuzzy_skin_perimeter_mode") == 0) + m_value = static_cast(ret_enum); + else if (m_opt_id.compare("fuzzy_skin_shape") == 0) + m_value = static_cast(ret_enum); else if (m_opt_id.compare("gcode_flavor") == 0) m_value = static_cast(ret_enum); else if (m_opt_id.compare("machine_limits_usage") == 0) diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index dea2260122..6b664c0edb 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -182,6 +182,10 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("ironing_type") == 0) config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); + else if (opt_key.compare("fuzzy_skin_perimeter_mode") == 0) + config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); + else if (opt_key.compare("fuzzy_skin_shape") == 0) + config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("gcode_flavor") == 0) config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("machine_limits_usage") == 0) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 36c1960d3f..71b1aa9ba2 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -410,6 +410,12 @@ void Preview::msw_rescale() refresh_print(); } +void Preview::sys_color_changed() +{ + if (m_layers_slider != nullptr) + m_layers_slider->sys_color_changed(); +} + void Preview::jump_layers_slider(wxKeyEvent& evt) { if (m_layers_slider) m_layers_slider->OnChar(evt); diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index 0060bfcffb..372d44fa31 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -150,6 +150,7 @@ public: void refresh_print(); void msw_rescale(); + void sys_color_changed(); void jump_layers_slider(wxKeyEvent& evt); void move_layers_slider(wxKeyEvent& evt); void edit_layers_slider(wxKeyEvent& evt); diff --git a/src/slic3r/GUI/GUI_Utils.hpp b/src/slic3r/GUI/GUI_Utils.hpp index 3235d6e9ea..dbb200f83b 100644 --- a/src/slic3r/GUI/GUI_Utils.hpp +++ b/src/slic3r/GUI/GUI_Utils.hpp @@ -108,6 +108,7 @@ public: // recalc_font(); +#ifndef __WXOSX__ #if wxVERSION_EQUAL_OR_GREATER_THAN(3,1,3) this->Bind(wxEVT_DPI_CHANGED, [this](wxDPIChangedEvent& evt) { m_scale_factor = (float)evt.GetNewDPI().x / (float)DPI_DEFAULT; @@ -128,6 +129,7 @@ public: rescale(evt.rect); }); #endif // wxVERSION_EQUAL_OR_GREATER_THAN +#endif // no __WXOSX__ this->Bind(wxEVT_MOVE_START, [this](wxMoveEvent& event) { diff --git a/src/slic3r/GUI/OG_CustomCtrl.cpp b/src/slic3r/GUI/OG_CustomCtrl.cpp index 07b96755da..1e581e70ba 100644 --- a/src/slic3r/GUI/OG_CustomCtrl.cpp +++ b/src/slic3r/GUI/OG_CustomCtrl.cpp @@ -360,6 +360,9 @@ void OG_CustomCtrl::correct_widgets_position(wxSizer* widget, const Line& line, void OG_CustomCtrl::msw_rescale() { +#ifdef __WXOSX__ + return; +#endif m_font = wxGetApp().normal_font(); m_em_unit = em_unit(m_parent); m_v_gap = lround(1.0 * m_em_unit); @@ -381,7 +384,6 @@ void OG_CustomCtrl::msw_rescale() void OG_CustomCtrl::sys_color_changed() { - msw_rescale(); } OG_CustomCtrl::CtrlLine::CtrlLine( wxCoord height, diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 10774abe3a..ced780adb6 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -870,6 +870,12 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config else if (opt_key == "ironing_type") { ret = static_cast(config.option>(opt_key)->value); } + else if (opt_key == "fuzzy_skin_perimeter_mode") { + ret = static_cast(config.option>(opt_key)->value); + } + else if (opt_key == "fuzzy_skin_shape") { + ret = static_cast(config.option>(opt_key)->value); + } else if (opt_key == "gcode_flavor") { ret = static_cast(config.option>(opt_key)->value); } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 41e9c8ff5c..f7f56f5701 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -6209,6 +6209,7 @@ void Plater::msw_rescale() void Plater::sys_color_changed() { + p->preview->sys_color_changed(); p->sidebar->sys_color_changed(); // msw_rescale_menu updates just icons, so use it diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index aec2f87542..974b709f7c 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1434,6 +1434,18 @@ void TabPrint::build() optgroup->append_single_option_line("seam_position", category_path + "seam-position"); optgroup->append_single_option_line("external_perimeters_first", category_path + "external-perimeters-first"); + optgroup = page->new_optgroup(L("Fuzzy skin (experimental)")); + Option option = optgroup->get_option("fuzzy_skin_perimeter_mode"); + option.opt.width = 30; + optgroup->append_single_option_line(option); +#if 0 + option = optgroup->get_option("fuzzy_skin_shape"); + option.opt.width = 30; + optgroup->append_single_option_line(option); +#endif + optgroup->append_single_option_line(optgroup->get_option("fuzzy_skin_thickness")); + optgroup->append_single_option_line(optgroup->get_option("fuzzy_skin_point_dist")); + page = add_options_page(L("Infill"), "infill"); category_path = "infill_42#"; optgroup = page->new_optgroup(L("Infill")); @@ -1597,7 +1609,7 @@ void TabPrint::build() optgroup = page->new_optgroup(L("Output file")); optgroup->append_single_option_line("gcode_comments"); optgroup->append_single_option_line("gcode_label_objects"); - Option option = optgroup->get_option("output_filename_format"); + option = optgroup->get_option("output_filename_format"); option.opt.full_width = true; optgroup->append_single_option_line(option);