mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-12 07:38:58 +08:00
Thumbnails refactoring: Next round
* Check errors state on all places of its using (throw exceptions or show a warnings message) + To backward compatibility, save "thumbnails_format" value to the config + deep_diff() function is extended for the case of "thumbnails" comparison + Added unit tests to: * check a load of configuration for "thumbnails" and "thumbnails_format" options * check return values for make_and_check_thumbnail_list() function
This commit is contained in:
parent
bae74457f7
commit
cfc520c97a
@ -874,8 +874,15 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
|
|||||||
|
|
||||||
// Unit tests or command line slicing may not define "thumbnails" or "thumbnails_format".
|
// Unit tests or command line slicing may not define "thumbnails" or "thumbnails_format".
|
||||||
// If "thumbnails_format" is not defined, export to PNG.
|
// If "thumbnails_format" is not defined, export to PNG.
|
||||||
if (std::vector<std::pair<GCodeThumbnailsFormat, Vec2d>> thumbnails = GCodeThumbnails::make_thumbnail_list(print.full_print_config());
|
auto [thumbnails, errors] = GCodeThumbnails::make_and_check_thumbnail_list(print.full_print_config());
|
||||||
! thumbnails.empty())
|
|
||||||
|
if (errors != enum_bitmask<ThumbnailError>()) {
|
||||||
|
std::string error_str = format("Invalid thumbnails value:");
|
||||||
|
error_str += GCodeThumbnails::get_error_string(errors);
|
||||||
|
throw Slic3r::ExportError(error_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!thumbnails.empty())
|
||||||
GCodeThumbnails::generate_binary_thumbnails(
|
GCodeThumbnails::generate_binary_thumbnails(
|
||||||
thumbnail_cb, binary_data.thumbnails, thumbnails,
|
thumbnail_cb, binary_data.thumbnails, thumbnails,
|
||||||
[&print]() { print.throw_if_canceled(); });
|
[&print]() { print.throw_if_canceled(); });
|
||||||
@ -1009,8 +1016,15 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
|
|||||||
|
|
||||||
if (! export_to_binary_gcode) {
|
if (! export_to_binary_gcode) {
|
||||||
// if exporting gcode in ascii format, generate the thumbnails here
|
// if exporting gcode in ascii format, generate the thumbnails here
|
||||||
if (std::vector<std::pair<GCodeThumbnailsFormat, Vec2d>> thumbnails = GCodeThumbnails::make_thumbnail_list(print.full_print_config());
|
auto [thumbnails, errors] = GCodeThumbnails::make_and_check_thumbnail_list(print.full_print_config());
|
||||||
! thumbnails.empty())
|
|
||||||
|
if (errors != enum_bitmask<ThumbnailError>()) {
|
||||||
|
std::string error_str = format("Invalid thumbnails value:");
|
||||||
|
error_str += GCodeThumbnails::get_error_string(errors);
|
||||||
|
throw Slic3r::ExportError(error_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!thumbnails.empty())
|
||||||
GCodeThumbnails::export_thumbnails_to_file(thumbnail_cb, thumbnails,
|
GCodeThumbnails::export_thumbnails_to_file(thumbnail_cb, thumbnails,
|
||||||
[&file](const char* sz) { file.write(sz); },
|
[&file](const char* sz) { file.write(sz); },
|
||||||
[&print]() { print.throw_if_canceled(); });
|
[&print]() { print.throw_if_canceled(); });
|
||||||
|
@ -123,27 +123,27 @@ std::unique_ptr<CompressedImageBuffer> compress_thumbnail(const ThumbnailData &d
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<GCodeThumbnailsFormat, Vec2d>> make_and_check_thumbnail_list(const std::string& thumbnails_string, ThumbnailErrors& errors, std::string def_ext /*= "PNG"*/)
|
std::pair<GCodeThumbnailDefinitionsList, ThumbnailErrors> make_and_check_thumbnail_list(const std::string& thumbnails_string, const std::string_view def_ext /*= "PNG"sv*/)
|
||||||
{
|
{
|
||||||
if (thumbnails_string.empty())
|
if (thumbnails_string.empty())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
const auto& extentions = ConfigOptionEnum<GCodeThumbnailsFormat>::get_enum_names();
|
|
||||||
|
|
||||||
std::istringstream is(thumbnails_string);
|
std::istringstream is(thumbnails_string);
|
||||||
std::string point_str;
|
std::string point_str;
|
||||||
|
|
||||||
|
ThumbnailErrors errors;
|
||||||
|
|
||||||
// generate thumbnails data to process it
|
// generate thumbnails data to process it
|
||||||
|
|
||||||
std::vector<std::pair<GCodeThumbnailsFormat, Vec2d>> thumbnails_list;
|
GCodeThumbnailDefinitionsList thumbnails_list;
|
||||||
while (std::getline(is, point_str, ',')) {
|
while (std::getline(is, point_str, ',')) {
|
||||||
Vec2d point(Vec2d::Zero());
|
Vec2d point(Vec2d::Zero());
|
||||||
GCodeThumbnailsFormat format;
|
GCodeThumbnailsFormat format;
|
||||||
std::istringstream iss(point_str);
|
std::istringstream iss(point_str);
|
||||||
std::string coord_str;
|
std::string coord_str;
|
||||||
if (std::getline(iss, coord_str, 'x')) {
|
if (std::getline(iss, coord_str, 'x') && !coord_str.empty()) {
|
||||||
std::istringstream(coord_str) >> point(0);
|
std::istringstream(coord_str) >> point(0);
|
||||||
if (std::getline(iss, coord_str, '/')) {
|
if (std::getline(iss, coord_str, '/') && !coord_str.empty()) {
|
||||||
std::istringstream(coord_str) >> point(1);
|
std::istringstream(coord_str) >> point(1);
|
||||||
|
|
||||||
if (0 < point(0) && point(0) < 1000 && 0 < point(1) && point(1) < 1000) {
|
if (0 < point(0) && point(0) < 1000 && 0 < point(1) && point(1) < 1000) {
|
||||||
@ -151,15 +151,15 @@ std::vector<std::pair<GCodeThumbnailsFormat, Vec2d>> make_and_check_thumbnail_li
|
|||||||
std::getline(iss, ext_str, '/');
|
std::getline(iss, ext_str, '/');
|
||||||
|
|
||||||
if (ext_str.empty())
|
if (ext_str.empty())
|
||||||
ext_str = def_ext;
|
ext_str = def_ext.empty() ? "PNG"sv : def_ext;
|
||||||
else {
|
|
||||||
// check validity of extention
|
// check validity of extention
|
||||||
boost::to_upper(ext_str);
|
boost::to_upper(ext_str);
|
||||||
if (std::find(extentions.begin(), extentions.end(), ext_str) == extentions.end())
|
if (!ConfigOptionEnum<GCodeThumbnailsFormat>::from_string(ext_str, format)) {
|
||||||
errors = enum_bitmask(errors | ThumbnailError::InvalidExt);
|
format = GCodeThumbnailsFormat::PNG;
|
||||||
|
errors = enum_bitmask(errors | ThumbnailError::InvalidExt);
|
||||||
}
|
}
|
||||||
format = ext_str == "JPG" ? GCodeThumbnailsFormat::JPG :
|
|
||||||
ext_str == "QOI" ? GCodeThumbnailsFormat::QOI : GCodeThumbnailsFormat::PNG;
|
|
||||||
thumbnails_list.emplace_back(std::make_pair(format, point));
|
thumbnails_list.emplace_back(std::make_pair(format, point));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -170,24 +170,34 @@ std::vector<std::pair<GCodeThumbnailsFormat, Vec2d>> make_and_check_thumbnail_li
|
|||||||
errors = enum_bitmask(errors | ThumbnailError::InvalidVal);
|
errors = enum_bitmask(errors | ThumbnailError::InvalidVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
return thumbnails_list;
|
return std::make_pair(std::move(thumbnails_list), errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<GCodeThumbnailsFormat, Vec2d>> make_thumbnail_list(const DynamicPrintConfig& config)
|
std::pair<GCodeThumbnailDefinitionsList, ThumbnailErrors> make_and_check_thumbnail_list(const ConfigBase& config)
|
||||||
{
|
{
|
||||||
// ??? Unit tests or command line slicing may not define "thumbnails" or "thumbnails_format".
|
// ??? Unit tests or command line slicing may not define "thumbnails" or "thumbnails_format".
|
||||||
// ??? If "thumbnails_format" is not defined, export to PNG.
|
// ??? If "thumbnails_format" is not defined, export to PNG.
|
||||||
|
|
||||||
// generate thumbnails data to process it
|
// generate thumbnails data to process it
|
||||||
|
|
||||||
std::vector<std::pair<GCodeThumbnailsFormat, Vec2d>> thumbnails_list;
|
if (const auto thumbnails_value = config.option<ConfigOptionString>("thumbnails"))
|
||||||
if (const auto thumbnails_value = config.option<ConfigOptionString>("thumbnails")) {
|
return make_and_check_thumbnail_list(thumbnails_value->value);
|
||||||
ThumbnailErrors errors;
|
|
||||||
thumbnails_list = make_and_check_thumbnail_list(thumbnails_value->value, errors);
|
|
||||||
assert(errors == enum_bitmask<ThumbnailError>());
|
|
||||||
}
|
|
||||||
|
|
||||||
return thumbnails_list;
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string get_error_string(const ThumbnailErrors& errors)
|
||||||
|
{
|
||||||
|
std::string error_str;
|
||||||
|
|
||||||
|
if (errors.has(ThumbnailError::InvalidVal))
|
||||||
|
error_str += "\n - " + format("Invalid input format. Expected vector of dimensions in the following format: \"%1%\"", "XxYxEXT, XxYxEXT, ...");
|
||||||
|
if (errors.has(ThumbnailError::OutOfRange))
|
||||||
|
error_str += "\n - Input value is out of range";
|
||||||
|
if (errors.has(ThumbnailError::InvalidExt))
|
||||||
|
error_str += "\n - Some input extention is invalid";
|
||||||
|
|
||||||
|
return error_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Slic3r::GCodeThumbnails
|
} // namespace Slic3r::GCodeThumbnails
|
||||||
|
@ -37,8 +37,13 @@ struct CompressedImageBuffer
|
|||||||
|
|
||||||
std::unique_ptr<CompressedImageBuffer> compress_thumbnail(const ThumbnailData &data, GCodeThumbnailsFormat format);
|
std::unique_ptr<CompressedImageBuffer> compress_thumbnail(const ThumbnailData &data, GCodeThumbnailsFormat format);
|
||||||
|
|
||||||
std::vector<std::pair<GCodeThumbnailsFormat, Vec2d>> make_and_check_thumbnail_list(const std::string& thumbnails_string, ThumbnailErrors& errors, std::string def_ext = "PNG");
|
typedef std::vector<std::pair<GCodeThumbnailsFormat, Vec2d>> GCodeThumbnailDefinitionsList;
|
||||||
std::vector<std::pair<GCodeThumbnailsFormat, Vec2d>> make_thumbnail_list(const DynamicPrintConfig &config);
|
|
||||||
|
using namespace std::literals;
|
||||||
|
std::pair<GCodeThumbnailDefinitionsList, ThumbnailErrors> make_and_check_thumbnail_list(const std::string& thumbnails_string, const std::string_view def_ext = "PNG"sv);
|
||||||
|
std::pair<GCodeThumbnailDefinitionsList, ThumbnailErrors> make_and_check_thumbnail_list(const ConfigBase &config);
|
||||||
|
|
||||||
|
std::string get_error_string(const ThumbnailErrors& errors);
|
||||||
|
|
||||||
template<typename WriteToOutput, typename ThrowIfCanceledCallback>
|
template<typename WriteToOutput, typename ThrowIfCanceledCallback>
|
||||||
inline void export_thumbnails_to_file(ThumbnailsGeneratorCallback &thumbnail_cb, const std::vector<std::pair<GCodeThumbnailsFormat, Vec2d>>& thumbnails_list, WriteToOutput output, ThrowIfCanceledCallback throw_if_canceled)
|
inline void export_thumbnails_to_file(ThumbnailsGeneratorCallback &thumbnail_cb, const std::vector<std::pair<GCodeThumbnailsFormat, Vec2d>>& thumbnails_list, WriteToOutput output, ThrowIfCanceledCallback throw_if_canceled)
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include "libslic3r.h"
|
#include "libslic3r.h"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
#include "PlaceholderParser.hpp"
|
#include "PlaceholderParser.hpp"
|
||||||
|
#include "GCode/Thumbnails.hpp"
|
||||||
|
|
||||||
using boost::property_tree::ptree;
|
using boost::property_tree::ptree;
|
||||||
|
|
||||||
@ -1299,7 +1300,6 @@ static const std::set<std::string> independent_from_extruder_number_options = {
|
|||||||
"filament_ramming_parameters",
|
"filament_ramming_parameters",
|
||||||
"gcode_substitutions",
|
"gcode_substitutions",
|
||||||
"post_process",
|
"post_process",
|
||||||
"thumbnails",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool PresetCollection::is_independent_from_extruder_number_option(const std::string& opt_key)
|
bool PresetCollection::is_independent_from_extruder_number_option(const std::string& opt_key)
|
||||||
@ -1323,6 +1323,15 @@ inline t_config_option_keys deep_diff(const ConfigBase &config_this, const Confi
|
|||||||
} else if (opt_key == "default_filament_profile") {
|
} else if (opt_key == "default_filament_profile") {
|
||||||
// Ignore this field, it is not presented to the user, therefore showing a "modified" flag for this parameter does not help.
|
// Ignore this field, it is not presented to the user, therefore showing a "modified" flag for this parameter does not help.
|
||||||
// Also the length of this field may differ, which may lead to a crash if the block below is used.
|
// Also the length of this field may differ, which may lead to a crash if the block below is used.
|
||||||
|
} else if (opt_key == "thumbnails") {
|
||||||
|
// "thumbnails" can not containes a extentions in old config but are valid and use PNG extention by default
|
||||||
|
// So, check if "thumbnails" is really changed
|
||||||
|
// We will compare full thumnails instead of exactly config values
|
||||||
|
auto [thumbnails, er] = GCodeThumbnails::make_and_check_thumbnail_list(config_this);
|
||||||
|
auto [thumbnails_new, er_new] = GCodeThumbnails::make_and_check_thumbnail_list(config_other);
|
||||||
|
if (thumbnails != thumbnails_new || er != er_new)
|
||||||
|
// if those strings are actually the same, erase them from the list of dirty oprions
|
||||||
|
diff.emplace_back(opt_key);
|
||||||
} else {
|
} else {
|
||||||
switch (other_opt->type()) {
|
switch (other_opt->type()) {
|
||||||
case coInts: add_correct_opts_to_diff<ConfigOptionInts >(opt_key, diff, config_other, config_this); break;
|
case coInts: add_correct_opts_to_diff<ConfigOptionInts >(opt_key, diff, config_other, config_this); break;
|
||||||
@ -1346,7 +1355,14 @@ bool PresetCollection::is_dirty(const Preset *edited, const Preset *reference)
|
|||||||
{
|
{
|
||||||
if (edited != nullptr && reference != nullptr) {
|
if (edited != nullptr && reference != nullptr) {
|
||||||
// Only compares options existing in both configs.
|
// Only compares options existing in both configs.
|
||||||
if (! reference->config.equals(edited->config))
|
bool is_dirty = !reference->config.equals(edited->config);
|
||||||
|
if (is_dirty && edited->type != Preset::TYPE_FILAMENT) {
|
||||||
|
// for non-filaments preset check deep difference for compared configs
|
||||||
|
// there can be cases (as for thumbnails), when configs can logically equal
|
||||||
|
// even when their values are not equal.
|
||||||
|
is_dirty = !deep_diff(edited->config, reference->config).empty();
|
||||||
|
}
|
||||||
|
if (is_dirty)
|
||||||
return true;
|
return true;
|
||||||
// The "compatible_printers" option key is handled differently from the others:
|
// The "compatible_printers" option key is handled differently from the others:
|
||||||
// It is not mandatory. If the key is missing, it means it is compatible with any printer.
|
// It is not mandatory. If the key is missing, it means it is compatible with any printer.
|
||||||
|
@ -4373,7 +4373,7 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
|||||||
void PrintConfigDef::handle_legacy_composite(DynamicPrintConfig &config)
|
void PrintConfigDef::handle_legacy_composite(DynamicPrintConfig &config)
|
||||||
{
|
{
|
||||||
if (config.has("thumbnails")) {
|
if (config.has("thumbnails")) {
|
||||||
std::string extention = "PNG";
|
std::string extention;
|
||||||
if (config.has("thumbnails_format")) {
|
if (config.has("thumbnails_format")) {
|
||||||
if (const ConfigOptionDef* opt = config.def()->get("thumbnails_format")) {
|
if (const ConfigOptionDef* opt = config.def()->get("thumbnails_format")) {
|
||||||
auto label = opt->enum_def->enum_to_label(config.option("thumbnails_format")->getInt());
|
auto label = opt->enum_def->enum_to_label(config.option("thumbnails_format")->getInt());
|
||||||
@ -4381,11 +4381,15 @@ void PrintConfigDef::handle_legacy_composite(DynamicPrintConfig &config)
|
|||||||
extention = *label;
|
extention = *label;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string thumbnails_str = config.opt_string("thumbnails");
|
|
||||||
|
|
||||||
ThumbnailErrors errors;
|
std::string thumbnails_str = config.opt_string("thumbnails");
|
||||||
auto thumbnails_list = GCodeThumbnails::make_and_check_thumbnail_list(thumbnails_str, errors, extention);
|
auto [thumbnails_list, errors] = GCodeThumbnails::make_and_check_thumbnail_list(thumbnails_str, extention);
|
||||||
assert(errors == enum_bitmask<ThumbnailError>());
|
|
||||||
|
if (errors != enum_bitmask<ThumbnailError>()) {
|
||||||
|
std::string error_str = "\n" + format("Invalid value provided for parameter %1%: %2%", "thumbnails", thumbnails_str);
|
||||||
|
error_str += GCodeThumbnails::get_error_string(errors);
|
||||||
|
throw BadOptionValueException(error_str);
|
||||||
|
}
|
||||||
|
|
||||||
if (!thumbnails_list.empty()) {
|
if (!thumbnails_list.empty()) {
|
||||||
const auto& extentions = ConfigOptionEnum<GCodeThumbnailsFormat>::get_enum_names();
|
const auto& extentions = ConfigOptionEnum<GCodeThumbnailsFormat>::get_enum_names();
|
||||||
|
@ -71,9 +71,8 @@ ThumbnailErrors validate_thumbnails_string(wxString& str, const wxString& def_ex
|
|||||||
std::string input_string = into_u8(str);
|
std::string input_string = into_u8(str);
|
||||||
|
|
||||||
str.Clear();
|
str.Clear();
|
||||||
ThumbnailErrors errors;
|
|
||||||
|
|
||||||
auto thumbnails_list = Slic3r::GCodeThumbnails::make_and_check_thumbnail_list(input_string, errors);
|
auto [thumbnails_list, errors] = GCodeThumbnails::make_and_check_thumbnail_list(input_string);
|
||||||
if (!thumbnails_list.empty()) {
|
if (!thumbnails_list.empty()) {
|
||||||
const auto& extentions = ConfigOptionEnum<GCodeThumbnailsFormat>::get_enum_names();
|
const auto& extentions = ConfigOptionEnum<GCodeThumbnailsFormat>::get_enum_names();
|
||||||
for (const auto& [format, size] : thumbnails_list)
|
for (const auto& [format, size] : thumbnails_list)
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "libslic3r/Model.hpp"
|
#include "libslic3r/Model.hpp"
|
||||||
#include "libslic3r/GCode/GCodeProcessor.hpp"
|
#include "libslic3r/GCode/GCodeProcessor.hpp"
|
||||||
#include "libslic3r/GCode/GCodeWriter.hpp"
|
#include "libslic3r/GCode/GCodeWriter.hpp"
|
||||||
|
#include "libslic3r/GCode/Thumbnails.hpp"
|
||||||
|
|
||||||
#include "slic3r/Utils/Http.hpp"
|
#include "slic3r/Utils/Http.hpp"
|
||||||
#include "slic3r/Utils/PrintHost.hpp"
|
#include "slic3r/Utils/PrintHost.hpp"
|
||||||
@ -2658,6 +2659,32 @@ void TabPrinter::build_fff()
|
|||||||
|
|
||||||
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
|
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
|
||||||
wxTheApp->CallAfter([this, opt_key, value]() {
|
wxTheApp->CallAfter([this, opt_key, value]() {
|
||||||
|
if (opt_key == "thumbnails" && m_config->has("thumbnails_format")) {
|
||||||
|
// to backward compatibility we need to update "thumbnails_format" from new "thumbnails"
|
||||||
|
if (const std::string val = boost::any_cast<std::string>(value); !value.empty()) {
|
||||||
|
auto [thumbnails_list, errors] = GCodeThumbnails::make_and_check_thumbnail_list(val);
|
||||||
|
|
||||||
|
if (errors != enum_bitmask<ThumbnailError>()) {
|
||||||
|
std::string error_str = format(_u8L("Invalid value provided for parameter %1%: %2%"), "thumbnails", val);
|
||||||
|
error_str += GCodeThumbnails::get_error_string(errors);
|
||||||
|
InfoDialog(parent(), _L("G-code flavor is switched"), from_u8(error_str)).ShowModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!thumbnails_list.empty()) {
|
||||||
|
GCodeThumbnailsFormat old_format = GCodeThumbnailsFormat(m_config->option("thumbnails_format")->getInt());
|
||||||
|
GCodeThumbnailsFormat new_format = thumbnails_list.begin()->first;
|
||||||
|
if (old_format != new_format) {
|
||||||
|
DynamicPrintConfig new_conf = *m_config;
|
||||||
|
|
||||||
|
auto* opt = m_config->option("thumbnails_format")->clone();
|
||||||
|
opt->setInt(int(new_format));
|
||||||
|
new_conf.set_key_value("thumbnails_format", opt);
|
||||||
|
|
||||||
|
load_config(new_conf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (opt_key == "silent_mode") {
|
if (opt_key == "silent_mode") {
|
||||||
bool val = boost::any_cast<bool>(value);
|
bool val = boost::any_cast<bool>(value);
|
||||||
if (m_use_silent_mode != val) {
|
if (m_use_silent_mode != val) {
|
||||||
|
@ -28,6 +28,7 @@ endif()
|
|||||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
|
|
||||||
add_subdirectory(arrange)
|
add_subdirectory(arrange)
|
||||||
|
add_subdirectory(thumbnails)
|
||||||
add_subdirectory(libslic3r)
|
add_subdirectory(libslic3r)
|
||||||
add_subdirectory(slic3rutils)
|
add_subdirectory(slic3rutils)
|
||||||
add_subdirectory(fff_print)
|
add_subdirectory(fff_print)
|
||||||
|
13
tests/thumbnails/CMakeLists.txt
Normal file
13
tests/thumbnails/CMakeLists.txt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
get_filename_component(_TEST_NAME ${CMAKE_CURRENT_LIST_DIR} NAME)
|
||||||
|
|
||||||
|
add_executable(${_TEST_NAME}_tests
|
||||||
|
${_TEST_NAME}_tests_main.cpp
|
||||||
|
test_thumbnails_input_string.cpp
|
||||||
|
test_thumbnails_ini_string.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(${_TEST_NAME}_tests test_common libslic3r)
|
||||||
|
set_property(TARGET ${_TEST_NAME}_tests PROPERTY FOLDER "tests")
|
||||||
|
|
||||||
|
# catch_discover_tests(${_TEST_NAME}_tests TEST_PREFIX "${_TEST_NAME}: ")
|
||||||
|
add_test(${_TEST_NAME}_tests ${_TEST_NAME}_tests ${CATCH_EXTRA_ARGS})
|
235
tests/thumbnails/test_thumbnails_ini_string.cpp
Normal file
235
tests/thumbnails/test_thumbnails_ini_string.cpp
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
#include "libslic3r/Config.hpp"
|
||||||
|
#include "libslic3r/PrintConfig.hpp"
|
||||||
|
|
||||||
|
#include <libslic3r/GCode/Thumbnails.hpp>
|
||||||
|
|
||||||
|
using namespace Slic3r;
|
||||||
|
using namespace GCodeThumbnails;
|
||||||
|
|
||||||
|
|
||||||
|
static std::string empty_thumbnails()
|
||||||
|
{
|
||||||
|
return "thumbnails = \n"
|
||||||
|
"thumbnails_format = ";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string valid_thumbnails()
|
||||||
|
{
|
||||||
|
return "thumbnails = 160x120/JPG, 23x78/QOI, 230x780/JPG\n"
|
||||||
|
"thumbnails_format = JPG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string valid_thumbnails2()
|
||||||
|
{
|
||||||
|
return "thumbnails = 160x120/PNG, 23x78/QOi, 320x240/PNg, 230x780/JPG\n"
|
||||||
|
"thumbnails_format = pnG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string valid_thumbnails3()
|
||||||
|
{
|
||||||
|
return "thumbnails = 160x120/JPG, 23x78/QOI, 230x780/JPG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string old_valid_thumbnails()
|
||||||
|
{
|
||||||
|
return "thumbnails = 160x120\n"
|
||||||
|
"thumbnails_format = JPG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string old_valid_thumbnails2()
|
||||||
|
{
|
||||||
|
return "thumbnails = 160x120, 23x78, 320x240\n"
|
||||||
|
"thumbnails_format = PNG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string old_invalid_thumbnails()
|
||||||
|
{
|
||||||
|
return "thumbnails = 160x\n"
|
||||||
|
"thumbnails_format = JPG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string old_invalid_thumbnails2()
|
||||||
|
{
|
||||||
|
return "thumbnails = 160x120, 23*78, 320x240\n"
|
||||||
|
"thumbnails_format = PNG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string out_of_range_thumbnails()
|
||||||
|
{
|
||||||
|
return "thumbnails = 1160x1200/PNG, 23x78/QOI, 320x240/PNG, 230x780/JPG\n"
|
||||||
|
"thumbnails_format = PNG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string out_of_range_thumbnails2()
|
||||||
|
{
|
||||||
|
return "thumbnails = 1160x120/PNG, 23x78/QOI, -320x240/PNG, 230x780/JPG\n"
|
||||||
|
"thumbnails_format = PNG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string invalid_ext_thumbnails()
|
||||||
|
{
|
||||||
|
return "thumbnails = 1160x120/PNk, 23x78/QOI, 320x240/PNG, 230x780/JPG\n"
|
||||||
|
"thumbnails_format = QOI";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string invalid_ext_thumbnails2()
|
||||||
|
{
|
||||||
|
return "thumbnails = 1160x120/PNG, 23x78/QO, 320x240/PNG, 230x780/JPG\n"
|
||||||
|
"thumbnails_format = PNG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string invalid_val_thumbnails()
|
||||||
|
{
|
||||||
|
return "thumbnails = 1160x/PNg, 23x78/QOI, 320x240/PNG, 230x780/JPG\n"
|
||||||
|
"thumbnails_format = JPG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string invalid_val_thumbnails2()
|
||||||
|
{
|
||||||
|
return "thumbnails = x120/PNg, 23x78/QOI, 320x240/PNG, 230x780/JPG\n"
|
||||||
|
"thumbnails_format = PNG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string invalid_val_thumbnails3()
|
||||||
|
{
|
||||||
|
return "thumbnails = 1x/PNg, 23x78/QOI, 320x240/PNG, 230x780/JPG\n"
|
||||||
|
"thumbnails_format = qoi";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string invalid_val_thumbnails4()
|
||||||
|
{
|
||||||
|
return "thumbnails = 123*78/QOI, 320x240/PNG, 230x780/JPG\n"
|
||||||
|
"thumbnails_format = jpG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static DynamicPrintConfig thumbnails_config()
|
||||||
|
{
|
||||||
|
DynamicPrintConfig config;
|
||||||
|
config.apply_only(FullPrintConfig::defaults() , { "thumbnails", "thumbnails_format" });
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Validate Empty Thumbnails", "[Thumbnails in Config]") {
|
||||||
|
DynamicPrintConfig config = thumbnails_config();
|
||||||
|
|
||||||
|
auto test_loaded_config = [](DynamicPrintConfig& config) {
|
||||||
|
REQUIRE(config.opt<ConfigOptionString>("thumbnails")->empty());
|
||||||
|
REQUIRE(config.option("thumbnails_format")->getInt() == (int)GCodeThumbnailsFormat::PNG);
|
||||||
|
};
|
||||||
|
|
||||||
|
SECTION("Load empty init_data") {
|
||||||
|
REQUIRE_NOTHROW(config.load_from_ini_string("", Enable));
|
||||||
|
test_loaded_config(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Load empty format and empty thumbnails") {
|
||||||
|
REQUIRE_THROWS_AS(config.load_from_ini_string(empty_thumbnails(), Enable), BadOptionValueException);
|
||||||
|
test_loaded_config(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Validate New Thumbnails", "[Thumbnails in Config]") {
|
||||||
|
|
||||||
|
DynamicPrintConfig config = thumbnails_config();
|
||||||
|
|
||||||
|
auto test_loaded_config = [](DynamicPrintConfig& config, GCodeThumbnailsFormat format) {
|
||||||
|
REQUIRE(!config.opt<ConfigOptionString>("thumbnails")->empty());
|
||||||
|
REQUIRE(config.option("thumbnails_format")->getInt() == (int)format);
|
||||||
|
};
|
||||||
|
|
||||||
|
SECTION("Test 1 (valid)") {
|
||||||
|
REQUIRE_NOTHROW(config.load_from_ini_string(valid_thumbnails(), Enable));
|
||||||
|
test_loaded_config(config, GCodeThumbnailsFormat::JPG);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test 2 (valid)") {
|
||||||
|
REQUIRE_NOTHROW(config.load_from_ini_string(valid_thumbnails2(), Enable));
|
||||||
|
test_loaded_config(config, GCodeThumbnailsFormat::PNG);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test 3 (valid)") {
|
||||||
|
REQUIRE_NOTHROW(config.load_from_ini_string(valid_thumbnails3(), Enable));
|
||||||
|
test_loaded_config(config, GCodeThumbnailsFormat::PNG);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SECTION("Test 1 (out_of_range)") {
|
||||||
|
REQUIRE_THROWS_AS(config.load_from_ini_string(out_of_range_thumbnails(), Enable), BadOptionValueException);
|
||||||
|
test_loaded_config(config, GCodeThumbnailsFormat::PNG);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test 2 (out_of_range)") {
|
||||||
|
REQUIRE_THROWS_AS(config.load_from_ini_string(out_of_range_thumbnails2(), Enable), BadOptionValueException);
|
||||||
|
test_loaded_config(config, GCodeThumbnailsFormat::PNG);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SECTION("Test 1 (invalid_ext)") {
|
||||||
|
REQUIRE_THROWS_AS(config.load_from_ini_string(invalid_ext_thumbnails(), Enable), BadOptionValueException);
|
||||||
|
test_loaded_config(config, GCodeThumbnailsFormat::QOI);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test 2 (invalid_ext)") {
|
||||||
|
REQUIRE_THROWS_AS(config.load_from_ini_string(invalid_ext_thumbnails2(), Enable), BadOptionValueException);
|
||||||
|
test_loaded_config(config, GCodeThumbnailsFormat::PNG);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SECTION("Test 1 (invalid_val)") {
|
||||||
|
REQUIRE_THROWS_AS(config.load_from_ini_string(invalid_val_thumbnails(), Enable), BadOptionValueException);
|
||||||
|
test_loaded_config(config, GCodeThumbnailsFormat::JPG);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test 2 (invalid_val)") {
|
||||||
|
REQUIRE_THROWS_AS(config.load_from_ini_string(invalid_val_thumbnails2(), Enable), BadOptionValueException);
|
||||||
|
test_loaded_config(config, GCodeThumbnailsFormat::PNG);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test 3 (invalid_val)") {
|
||||||
|
REQUIRE_THROWS_AS(config.load_from_ini_string(invalid_val_thumbnails3(), Enable), BadOptionValueException);
|
||||||
|
test_loaded_config(config, GCodeThumbnailsFormat::PNG);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test 4 (invalid_val)") {
|
||||||
|
REQUIRE_THROWS_AS(config.load_from_ini_string(invalid_val_thumbnails4(), Enable), BadOptionValueException);
|
||||||
|
test_loaded_config(config, GCodeThumbnailsFormat::PNG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Validate Old Thumbnails", "[Thumbnails in Config]") {
|
||||||
|
|
||||||
|
DynamicPrintConfig config = thumbnails_config();
|
||||||
|
|
||||||
|
auto test_loaded_config = [](DynamicPrintConfig& config, GCodeThumbnailsFormat format) {
|
||||||
|
REQUIRE(!config.opt<ConfigOptionString>("thumbnails")->empty());
|
||||||
|
REQUIRE(config.option("thumbnails_format")->getInt() == (int)format);
|
||||||
|
};
|
||||||
|
|
||||||
|
SECTION("Test 1 (valid)") {
|
||||||
|
REQUIRE_NOTHROW(config.load_from_ini_string(old_valid_thumbnails(), Enable));
|
||||||
|
test_loaded_config(config, GCodeThumbnailsFormat::JPG);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test 2 (valid)") {
|
||||||
|
REQUIRE_NOTHROW(config.load_from_ini_string(old_valid_thumbnails2(), Enable));
|
||||||
|
test_loaded_config(config, GCodeThumbnailsFormat::PNG);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test 1 (invalid)") {
|
||||||
|
REQUIRE_THROWS_AS(config.load_from_ini_string(old_invalid_thumbnails(), Enable), BadOptionValueException);
|
||||||
|
test_loaded_config(config, GCodeThumbnailsFormat::JPG);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test 2 (invalid)") {
|
||||||
|
REQUIRE_THROWS_AS(config.load_from_ini_string(old_invalid_thumbnails2(), Enable), BadOptionValueException);
|
||||||
|
test_loaded_config(config, GCodeThumbnailsFormat::PNG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
152
tests/thumbnails/test_thumbnails_input_string.cpp
Normal file
152
tests/thumbnails/test_thumbnails_input_string.cpp
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
#include <catch2/catch.hpp>
|
||||||
|
#include <test_utils.hpp>
|
||||||
|
|
||||||
|
#include <libslic3r/GCode/Thumbnails.hpp>
|
||||||
|
|
||||||
|
using namespace Slic3r;
|
||||||
|
using namespace GCodeThumbnails;
|
||||||
|
|
||||||
|
|
||||||
|
// Test Thumbnails lines
|
||||||
|
|
||||||
|
static std::string empty_thumbnails()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string valid_thumbnails()
|
||||||
|
{
|
||||||
|
return "160x120/PNG, 23x78/QOI, 230x780/JPG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string valid_thumbnails2()
|
||||||
|
{
|
||||||
|
return "160x120/PNG, 23x78/QOi, 320x240/PNg, 230x780/JPG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string out_of_range_thumbnail()
|
||||||
|
{
|
||||||
|
return "160x1200/PNG, 23x78/QOI, 320x240/PNG, 230x780/JPG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string out_of_range_thumbnail2()
|
||||||
|
{
|
||||||
|
return "160x120/PNG, 23x78/QOI, -320x240/PNG, 230x780/JPG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string invalid_ext_thumbnail()
|
||||||
|
{
|
||||||
|
return "160x120/PNk, 23x78/QOI, 320x240/PNG, 230x780/JPG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string invalid_ext_thumbnail2()
|
||||||
|
{
|
||||||
|
return "160x120/PNG, 23x78/QO, 320x240/PNG, 230x780/JPG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string invalid_val_thumbnail()
|
||||||
|
{
|
||||||
|
return "160x/PNg, 23x78/QOI, 320x240/PNG, 230x780/JPG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string invalid_val_thumbnail2()
|
||||||
|
{
|
||||||
|
return "x120/PNg, 23x78/QOI, 320x240/PNG, 230x780/JPG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string invalid_val_thumbnail3()
|
||||||
|
{
|
||||||
|
return "x/PNg, 23x78/QOI, 320x240/PNG, 230x780/JPG";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string invalid_val_thumbnail4()
|
||||||
|
{
|
||||||
|
return "23*78/QOI, 320x240/PNG, 230x780/JPG";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("Empty Thumbnails", "[Thumbnails]") {
|
||||||
|
auto [thumbnails, errors] = make_and_check_thumbnail_list(empty_thumbnails());
|
||||||
|
REQUIRE(errors == enum_bitmask<ThumbnailError>());
|
||||||
|
REQUIRE(thumbnails.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Valid Thumbnails", "[Thumbnails]") {
|
||||||
|
|
||||||
|
SECTION("Test 1") {
|
||||||
|
auto [thumbnails, errors] = make_and_check_thumbnail_list(valid_thumbnails());
|
||||||
|
REQUIRE(errors == enum_bitmask<ThumbnailError>());
|
||||||
|
REQUIRE(thumbnails.size() == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test 2") {
|
||||||
|
auto [thumbnails, errors] = make_and_check_thumbnail_list(valid_thumbnails2());
|
||||||
|
REQUIRE(errors == enum_bitmask<ThumbnailError>());
|
||||||
|
REQUIRE(thumbnails.size() == 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Out of range Thumbnails", "[Thumbnails]") {
|
||||||
|
|
||||||
|
SECTION("Test 1") {
|
||||||
|
auto [thumbnails, errors] = make_and_check_thumbnail_list(out_of_range_thumbnail());
|
||||||
|
REQUIRE(errors != enum_bitmask<ThumbnailError>());
|
||||||
|
REQUIRE(errors.has(ThumbnailError::OutOfRange));
|
||||||
|
REQUIRE(thumbnails.size() == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test 2") {
|
||||||
|
auto [thumbnails, errors] = make_and_check_thumbnail_list(out_of_range_thumbnail2());
|
||||||
|
REQUIRE(errors != enum_bitmask<ThumbnailError>());
|
||||||
|
REQUIRE(errors.has(ThumbnailError::OutOfRange));
|
||||||
|
REQUIRE(thumbnails.size() == 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Invalid extention Thumbnails", "[Thumbnails]") {
|
||||||
|
|
||||||
|
SECTION("Test 1") {
|
||||||
|
auto [thumbnails, errors] = make_and_check_thumbnail_list(invalid_ext_thumbnail());
|
||||||
|
REQUIRE(errors != enum_bitmask<ThumbnailError>());
|
||||||
|
REQUIRE(errors.has(ThumbnailError::InvalidExt));
|
||||||
|
REQUIRE(thumbnails.size() == 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test 2") {
|
||||||
|
auto [thumbnails, errors] = make_and_check_thumbnail_list(invalid_ext_thumbnail2());
|
||||||
|
REQUIRE(errors != enum_bitmask<ThumbnailError>());
|
||||||
|
REQUIRE(errors.has(ThumbnailError::InvalidExt));
|
||||||
|
REQUIRE(thumbnails.size() == 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Invalid value Thumbnails", "[Thumbnails]") {
|
||||||
|
|
||||||
|
SECTION("Test 1") {
|
||||||
|
auto [thumbnails, errors] = make_and_check_thumbnail_list(invalid_val_thumbnail());
|
||||||
|
REQUIRE(errors != enum_bitmask<ThumbnailError>());
|
||||||
|
REQUIRE(errors.has(ThumbnailError::InvalidVal));
|
||||||
|
REQUIRE(thumbnails.size() == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test 2") {
|
||||||
|
auto [thumbnails, errors] = make_and_check_thumbnail_list(invalid_val_thumbnail2());
|
||||||
|
REQUIRE(errors != enum_bitmask<ThumbnailError>());
|
||||||
|
REQUIRE(errors.has(ThumbnailError::InvalidVal));
|
||||||
|
REQUIRE(thumbnails.size() == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test 3") {
|
||||||
|
auto [thumbnails, errors] = make_and_check_thumbnail_list(invalid_val_thumbnail3());
|
||||||
|
REQUIRE(errors != enum_bitmask<ThumbnailError>());
|
||||||
|
REQUIRE(errors.has(ThumbnailError::InvalidVal));
|
||||||
|
REQUIRE(thumbnails.size() == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Test 4") {
|
||||||
|
auto [thumbnails, errors] = make_and_check_thumbnail_list(invalid_val_thumbnail4());
|
||||||
|
REQUIRE(errors != enum_bitmask<ThumbnailError>());
|
||||||
|
REQUIRE(errors.has(ThumbnailError::InvalidVal));
|
||||||
|
REQUIRE(thumbnails.size() == 2);
|
||||||
|
}
|
||||||
|
}
|
1
tests/thumbnails/thumbnails_tests_main.cpp
Normal file
1
tests/thumbnails/thumbnails_tests_main.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include <catch_main.hpp>
|
Loading…
x
Reference in New Issue
Block a user