mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 12:41:20 -06:00 
			
		
		
		
	Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer
This commit is contained in:
		
						commit
						63f31ce4db
					
				
					 14 changed files with 302 additions and 108 deletions
				
			
		|  | @ -37,7 +37,7 @@ set(SLIC3R_GTK "2" CACHE STRING "GTK version to use with wxWidgets on Linux") | |||
| 
 | ||||
| # Proposal for C++ unit tests and sandboxes | ||||
| option(SLIC3R_BUILD_SANDBOXES   "Build development sandboxes" OFF) | ||||
| option(SLIC3R_BUILD_TESTS       "Build unit tests" OFF) | ||||
| option(SLIC3R_BUILD_TESTS       "Build unit tests" ON) | ||||
| 
 | ||||
| # Print out the SLIC3R_* cache options | ||||
| get_cmake_property(_cache_vars CACHE_VARIABLES) | ||||
|  |  | |||
|  | @ -271,8 +271,6 @@ ConfigOptionDef* ConfigDef::add_nullable(const t_config_option_key &opt_key, Con | |||
| 	return def; | ||||
| } | ||||
| 
 | ||||
| std::string ConfigOptionDef::nocli = "~~~noCLI"; | ||||
| 
 | ||||
| std::ostream& ConfigDef::print_cli_help(std::ostream& out, bool show_defaults, std::function<bool(const ConfigOptionDef &)> filter) const | ||||
| { | ||||
|     // prepare a function for wrapping text
 | ||||
|  |  | |||
|  | @ -1444,7 +1444,7 @@ public: | |||
|     std::vector<std::string> cli_args(const std::string &key) const; | ||||
| 
 | ||||
|     // Assign this key to cli to disable CLI for this option.
 | ||||
|     static std::string                  nocli; | ||||
|     static const constexpr char *nocli =  "~~~noCLI"; | ||||
| }; | ||||
| 
 | ||||
| // Map from a config option name to its definition.
 | ||||
|  |  | |||
|  | @ -114,7 +114,7 @@ void SLARasterWriter::set_config(const DynamicPrintConfig &cfg) | |||
|     m_config["printerProfile"] = get_cfg_value(cfg, "printer_settings_id"); | ||||
|     m_config["printProfile"]   = get_cfg_value(cfg, "sla_print_settings_id"); | ||||
| 
 | ||||
|     m_config["fileCreationTimestamp"] = Utils::current_utc_time2str(); | ||||
|     m_config["fileCreationTimestamp"] = Utils::utc_timestamp(); | ||||
|     m_config["prusaSlicerVersion"]    = SLIC3R_BUILD_ID; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,116 +3,232 @@ | |||
| #include <iomanip> | ||||
| #include <sstream> | ||||
| #include <chrono> | ||||
| #include <cassert> | ||||
| #include <ctime> | ||||
| #include <cstdio> | ||||
| 
 | ||||
| //#include <boost/date_time/local_time/local_time.hpp>
 | ||||
| //#include <boost/chrono.hpp>
 | ||||
| #ifdef _MSC_VER | ||||
| #include <map> | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| #ifdef WIN32 | ||||
| 	#define WIN32_LEAN_AND_MEAN | ||||
| 	#include <windows.h> | ||||
| 	#undef WIN32_LEAN_AND_MEAN | ||||
| #endif /* WIN32 */ | ||||
| #include "libslic3r/Utils.hpp" | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| namespace Utils { | ||||
| 
 | ||||
| namespace  { | ||||
| // "YYYY-MM-DD at HH:MM::SS [UTC]"
 | ||||
| // If TimeZone::utc is used with the conversion functions, it will append the
 | ||||
| // UTC letters to the end.
 | ||||
| static const constexpr char *const SLICER_UTC_TIME_FMT = "%Y-%m-%d at %T"; | ||||
| 
 | ||||
| // FIXME: after we switch to gcc > 4.9 on the build server, please remove me
 | ||||
| #if defined(__GNUC__) && __GNUC__ <= 4 | ||||
| std::string put_time(const std::tm *tm, const char *fmt) | ||||
| // ISO8601Z representation of time, without time zone info
 | ||||
| static const constexpr char *const ISO8601Z_TIME_FMT = "%Y%m%dT%H%M%SZ"; | ||||
| 
 | ||||
| static const char * get_fmtstr(TimeFormat fmt) | ||||
| { | ||||
|     static const constexpr int MAX_CHARS = 200; | ||||
|     char out[MAX_CHARS]; | ||||
|     std::strftime(out, MAX_CHARS, fmt, tm); | ||||
|     return out; | ||||
|     switch (fmt) { | ||||
|     case TimeFormat::gcode: return SLICER_UTC_TIME_FMT; | ||||
|     case TimeFormat::iso8601Z: return ISO8601Z_TIME_FMT; | ||||
|     } | ||||
| 
 | ||||
|     return ""; | ||||
| } | ||||
| #else | ||||
| auto put_time(const std::tm *tm, const char *fmt) -> decltype (std::put_time(tm, fmt)) | ||||
| 
 | ||||
| namespace __get_put_time_emulation { | ||||
| // FIXME: Implementations with the cpp11 put_time and get_time either not
 | ||||
| // compile or do not pass the tests on the build server. If we switch to newer
 | ||||
| // compilers, this namespace can be deleted with all its content.
 | ||||
| 
 | ||||
| #ifdef _MSC_VER | ||||
| // VS2019 implementation fails with ISO8601Z_TIME_FMT.
 | ||||
| // VS2019 does not have std::strptime either. See bug:
 | ||||
| // https://developercommunity.visualstudio.com/content/problem/140618/c-stdget-time-not-parsing-correctly.html
 | ||||
| 
 | ||||
| static const std::map<std::string, std::string> sscanf_fmt_map = { | ||||
|     {SLICER_UTC_TIME_FMT, "%04d-%02d-%02d at %02d:%02d:%02d"}, | ||||
|     {std::string(SLICER_UTC_TIME_FMT) + " UTC", "%04d-%02d-%02d at %02d:%02d:%02d UTC"}, | ||||
|     {ISO8601Z_TIME_FMT, "%04d%02d%02dT%02d%02d%02dZ"} | ||||
| }; | ||||
| 
 | ||||
| static const char * strptime(const char *str, const char *const fmt, std::tm *tms) | ||||
| { | ||||
|     return std::put_time(tm, fmt); | ||||
|     auto it = sscanf_fmt_map.find(fmt); | ||||
|     if (it == sscanf_fmt_map.end()) return nullptr; | ||||
| 
 | ||||
|     int y, M, d, h, m, s; | ||||
|     if (sscanf(str, it->second.c_str(), &y, &M, &d, &h, &m, &s) != 6) | ||||
|         return nullptr; | ||||
| 
 | ||||
|     tms->tm_year = y - 1900;  // Year since 1900
 | ||||
|     tms->tm_mon  = M - 1;     // 0-11
 | ||||
|     tms->tm_mday = d;         // 1-31
 | ||||
|     tms->tm_hour = h;         // 0-23
 | ||||
|     tms->tm_min  = m;         // 0-59
 | ||||
|     tms->tm_sec  = s;         // 0-61 (0-60 in C++11)
 | ||||
| 
 | ||||
|     return str; // WARN strptime return val should point after the parsed string
 | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| template<class Ttm> | ||||
| struct GetPutTimeReturnT { | ||||
|     Ttm *tms; | ||||
|     const char *fmt; | ||||
|     GetPutTimeReturnT(Ttm *_tms, const char *_fmt): tms(_tms), fmt(_fmt) {} | ||||
| }; | ||||
| 
 | ||||
| using GetTimeReturnT = GetPutTimeReturnT<std::tm>; | ||||
| using PutTimeReturnT = GetPutTimeReturnT<const std::tm>; | ||||
| 
 | ||||
| std::ostream &operator<<(std::ostream &stream, PutTimeReturnT &&pt) | ||||
| { | ||||
|     static const constexpr int MAX_CHARS = 200; | ||||
|     char _out[MAX_CHARS]; | ||||
|     strftime(_out, MAX_CHARS, pt.fmt, pt.tms); | ||||
|     stream << _out; | ||||
|     return stream; | ||||
| } | ||||
| 
 | ||||
| time_t parse_time_ISO8601Z(const std::string &sdate) | ||||
| inline PutTimeReturnT put_time(const std::tm *tms, const char *fmt) | ||||
| { | ||||
| 	int y, M, d, h, m, s; | ||||
| 	if (sscanf(sdate.c_str(), "%04d%02d%02dT%02d%02d%02dZ", &y, &M, &d, &h, &m, &s) != 6) | ||||
|         return time_t(-1); | ||||
| 	struct tm tms; | ||||
|     tms.tm_year = y - 1900;  // Year since 1900
 | ||||
| 	tms.tm_mon  = M - 1;     // 0-11
 | ||||
| 	tms.tm_mday = d;         // 1-31
 | ||||
| 	tms.tm_hour = h;         // 0-23
 | ||||
| 	tms.tm_min  = m;         // 0-59
 | ||||
| 	tms.tm_sec  = s;         // 0-61 (0-60 in C++11)
 | ||||
|     return {tms, fmt}; | ||||
| } | ||||
| 
 | ||||
| std::istream &operator>>(std::istream &stream, GetTimeReturnT &>) | ||||
| { | ||||
|     std::string line; | ||||
|     std::getline(stream, line); | ||||
| 
 | ||||
|     if (strptime(line.c_str(), gt.fmt, gt.tms) == nullptr) | ||||
|         stream.setstate(std::ios::failbit); | ||||
| 
 | ||||
|     return stream; | ||||
| } | ||||
| 
 | ||||
| inline GetTimeReturnT get_time(std::tm *tms, const char *fmt) | ||||
| { | ||||
|     return {tms, fmt}; | ||||
| } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| // Platform independent versions of gmtime and localtime. Completely thread
 | ||||
| // safe only on Linux. MSVC gtime_s and localtime_s sets global errno thus not
 | ||||
| // thread safe.
 | ||||
| struct std::tm * _gmtime_r(const time_t *timep, struct tm *result) | ||||
| { | ||||
|     assert(timep != nullptr && result != nullptr); | ||||
| #ifdef WIN32 | ||||
| 	return _mkgmtime(&tms); | ||||
|     time_t t = *timep; | ||||
|     gmtime_s(result, &t); | ||||
|     return result; | ||||
| #else | ||||
|     return gmtime_r(timep, result); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| struct std::tm * _localtime_r(const time_t *timep, struct tm *result) | ||||
| { | ||||
|     assert(timep != nullptr && result != nullptr); | ||||
| #ifdef WIN32 | ||||
|     // Converts a time_t time value to a tm structure, and corrects for the
 | ||||
|     // local time zone.
 | ||||
|     time_t t = *timep; | ||||
|     localtime_s(result, &t); | ||||
|     return result; | ||||
| #else | ||||
|     return localtime_r(timep, result); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| time_t _mktime(const struct std::tm *tms) | ||||
| { | ||||
|     assert(tms != nullptr); | ||||
|     std::tm _tms = *tms; | ||||
|     return mktime(&_tms); | ||||
| } | ||||
| 
 | ||||
| time_t _timegm(const struct std::tm *tms) | ||||
| { | ||||
|     std::tm _tms = *tms; | ||||
| #ifdef WIN32 | ||||
|     return _mkgmtime(&_tms); | ||||
| #else /* WIN32 */ | ||||
| 	return timegm(&tms); | ||||
|     return timegm(&_tms); | ||||
| #endif /* WIN32 */ | ||||
| } | ||||
| 
 | ||||
| std::string format_time_ISO8601Z(time_t time) | ||||
| std::string process_format(const char *fmt, TimeZone zone) | ||||
| { | ||||
| 	struct tm tms; | ||||
| #ifdef WIN32 | ||||
| 	gmtime_s(&tms, &time); | ||||
| #else | ||||
| 	gmtime_r(&time, &tms); | ||||
| #endif | ||||
| 	char buf[128]; | ||||
| 	sprintf(buf, "%04d%02d%02dT%02d%02d%02dZ", | ||||
|     	tms.tm_year + 1900, | ||||
| 		tms.tm_mon + 1, | ||||
| 		tms.tm_mday, | ||||
| 		tms.tm_hour, | ||||
| 		tms.tm_min, | ||||
| 		tms.tm_sec); | ||||
| 	return buf; | ||||
|     std::string fmtstr(fmt); | ||||
| 
 | ||||
|     if (fmtstr == SLICER_UTC_TIME_FMT && zone == TimeZone::utc) | ||||
|         fmtstr += " UTC"; | ||||
| 
 | ||||
|     return fmtstr; | ||||
| } | ||||
| 
 | ||||
| std::string format_local_date_time(time_t time) | ||||
| { | ||||
| 	struct tm tms; | ||||
| #ifdef WIN32 | ||||
| 	// Converts a time_t time value to a tm structure, and corrects for the local time zone.
 | ||||
| 	localtime_s(&tms, &time); | ||||
| #else | ||||
| 	localtime_r(&time, &tms); | ||||
| #endif | ||||
|     char buf[80]; | ||||
|  	strftime(buf, 80, "%x %X", &tms); | ||||
|     return buf; | ||||
| } | ||||
| } // namespace
 | ||||
| 
 | ||||
| time_t get_current_time_utc() | ||||
| {     | ||||
| { | ||||
|     using clk = std::chrono::system_clock; | ||||
|     return clk::to_time_t(clk::now()); | ||||
| } | ||||
| 
 | ||||
| static std::string tm2str(const std::tm *tm, const char *fmt) | ||||
| static std::string tm2str(const std::tm *tms, const char *fmt) | ||||
| { | ||||
|     std::stringstream ss; | ||||
|     ss << put_time(tm, fmt); | ||||
|     ss.imbue(std::locale("C")); | ||||
|     ss << __get_put_time_emulation::put_time(tms, fmt); | ||||
|     return ss.str(); | ||||
| } | ||||
| 
 | ||||
| std::string time2str(const time_t &t, TimeZone zone, const char *fmt) | ||||
| std::string time2str(const time_t &t, TimeZone zone, TimeFormat fmt) | ||||
| { | ||||
|     std::string ret; | ||||
|      | ||||
|     std::tm tms = {}; | ||||
|     tms.tm_isdst = -1; | ||||
|     std::string fmtstr = process_format(get_fmtstr(fmt), zone); | ||||
| 
 | ||||
|     switch (zone) { | ||||
|     case TimeZone::local: ret = tm2str(std::localtime(&t), fmt); break; | ||||
|     case TimeZone::utc:   ret = tm2str(std::gmtime(&t), fmt) + " UTC"; break; | ||||
|     case TimeZone::local: | ||||
|         ret = tm2str(_localtime_r(&t, &tms), fmtstr.c_str()); break; | ||||
|     case TimeZone::utc: | ||||
|         ret = tm2str(_gmtime_r(&t, &tms), fmtstr.c_str()); break; | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static time_t str2time(std::istream &stream, TimeZone zone, const char *fmt) | ||||
| { | ||||
|     std::tm tms = {}; | ||||
|     tms.tm_isdst = -1; | ||||
| 
 | ||||
|     stream >> __get_put_time_emulation::get_time(&tms, fmt); | ||||
|     time_t ret = time_t(-1); | ||||
| 
 | ||||
|     switch (zone) { | ||||
|     case TimeZone::local: ret = _mktime(&tms); break; | ||||
|     case TimeZone::utc:   ret = _timegm(&tms); break; | ||||
|     } | ||||
| 
 | ||||
|     if (stream.fail() || ret < time_t(0)) ret = time_t(-1); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| time_t str2time(const std::string &str, TimeZone zone, TimeFormat fmt) | ||||
| { | ||||
|     std::string fmtstr = process_format(get_fmtstr(fmt), zone).c_str(); | ||||
|     std::stringstream ss(str); | ||||
| 
 | ||||
|     ss.imbue(std::locale("C")); | ||||
|     return str2time(ss, zone, fmtstr.c_str()); | ||||
| } | ||||
| 
 | ||||
| }; // namespace Utils
 | ||||
| }; // namespace Slic3r
 | ||||
|  |  | |||
|  | @ -7,41 +7,61 @@ | |||
| namespace Slic3r { | ||||
| namespace Utils { | ||||
| 
 | ||||
| // Utilities to convert an UTC time_t to/from an ISO8601 time format,
 | ||||
| // useful for putting timestamps into file and directory names.
 | ||||
| // Returns (time_t)-1 on error.
 | ||||
| time_t parse_time_ISO8601Z(const std::string &s); | ||||
| std::string format_time_ISO8601Z(time_t time); | ||||
| 
 | ||||
| // Format the date and time from an UTC time according to the active locales and a local time zone.
 | ||||
| // TODO: make sure time2str is a suitable replacement
 | ||||
| std::string format_local_date_time(time_t time); | ||||
| 
 | ||||
| // There is no gmtime() on windows.
 | ||||
| // Should be thread safe.
 | ||||
| time_t get_current_time_utc(); | ||||
| 
 | ||||
| const constexpr char *const SLIC3R_TIME_FMT = "%Y-%m-%d at %T"; | ||||
| 
 | ||||
| enum class TimeZone { local, utc }; | ||||
| enum class TimeFormat { gcode, iso8601Z }; | ||||
| 
 | ||||
| std::string time2str(const time_t &t, TimeZone zone, const char *fmt = SLIC3R_TIME_FMT); | ||||
| // time_t to string functions...
 | ||||
| 
 | ||||
| inline std::string current_time2str(TimeZone zone, const char *fmt = SLIC3R_TIME_FMT) | ||||
| std::string time2str(const time_t &t, TimeZone zone, TimeFormat fmt); | ||||
| 
 | ||||
| inline std::string time2str(TimeZone zone, TimeFormat fmt) | ||||
| { | ||||
|     return time2str(get_current_time_utc(), zone, fmt); | ||||
| } | ||||
| 
 | ||||
| inline std::string current_local_time2str(const char * fmt = SLIC3R_TIME_FMT) | ||||
| inline std::string utc_timestamp(time_t t) | ||||
| { | ||||
|     return current_time2str(TimeZone::local, fmt);     | ||||
|     return time2str(t, TimeZone::utc, TimeFormat::gcode); | ||||
| } | ||||
| 
 | ||||
| inline std::string current_utc_time2str(const char * fmt = SLIC3R_TIME_FMT) | ||||
| inline std::string utc_timestamp() | ||||
| { | ||||
|     return current_time2str(TimeZone::utc, fmt); | ||||
|     return utc_timestamp(get_current_time_utc()); | ||||
| } | ||||
| 
 | ||||
| }; // namespace Utils
 | ||||
| }; // namespace Slic3r
 | ||||
| // String to time_t function. Returns time_t(-1) if fails to parse the input.
 | ||||
| time_t str2time(const std::string &str, TimeZone zone, TimeFormat fmt); | ||||
| 
 | ||||
| 
 | ||||
| // /////////////////////////////////////////////////////////////////////////////
 | ||||
| // Utilities to convert an UTC time_t to/from an ISO8601 time format,
 | ||||
| // useful for putting timestamps into file and directory names.
 | ||||
| // Returns (time_t)-1 on error.
 | ||||
| 
 | ||||
| // Use these functions to convert safely to and from the ISO8601 format on
 | ||||
| // all platforms
 | ||||
| 
 | ||||
| inline std::string iso_utc_timestamp(time_t t) | ||||
| { | ||||
|     return time2str(t, TimeZone::utc, TimeFormat::gcode); | ||||
| } | ||||
| 
 | ||||
| inline std::string iso_utc_timestamp() | ||||
| { | ||||
|     return iso_utc_timestamp(get_current_time_utc()); | ||||
| } | ||||
| 
 | ||||
| inline time_t parse_iso_utc_timestamp(const std::string &str) | ||||
| { | ||||
|     return str2time(str, TimeZone::utc, TimeFormat::iso8601Z); | ||||
| } | ||||
| 
 | ||||
| // /////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| } // namespace Utils
 | ||||
| } // namespace Slic3r
 | ||||
| 
 | ||||
| #endif /* slic3r_Utils_Time_hpp_ */ | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| #include <utility> | ||||
| #include <functional> | ||||
| #include <type_traits> | ||||
| #include <system_error> | ||||
| 
 | ||||
| #include "libslic3r.h" | ||||
| 
 | ||||
|  |  | |||
|  | @ -543,7 +543,7 @@ std::string string_printf(const char *format, ...) | |||
| 
 | ||||
| std::string header_slic3r_generated() | ||||
| { | ||||
|     return std::string("generated by " SLIC3R_APP_NAME " " SLIC3R_VERSION " on " ) + Utils::current_utc_time2str(); | ||||
|     return std::string("generated by " SLIC3R_APP_NAME " " SLIC3R_VERSION " on " ) + Utils::utc_timestamp(); | ||||
| } | ||||
| 
 | ||||
| unsigned get_current_pid() | ||||
|  |  | |||
|  | @ -66,7 +66,7 @@ void Snapshot::load_ini(const std::string &path) | |||
|                 if (kvp.first == "id") | ||||
|                     this->id = kvp.second.data(); | ||||
|                 else if (kvp.first == "time_captured") { | ||||
|                 	this->time_captured = Slic3r::Utils::parse_time_ISO8601Z(kvp.second.data()); | ||||
|                 	this->time_captured = Slic3r::Utils::parse_iso_utc_timestamp(kvp.second.data()); | ||||
| 					if (this->time_captured == (time_t)-1) | ||||
| 				        throw_on_parse_error("invalid timestamp"); | ||||
|                 } else if (kvp.first == "slic3r_version_captured") { | ||||
|  | @ -165,7 +165,7 @@ void Snapshot::save_ini(const std::string &path) | |||
|     // Export the common "snapshot".
 | ||||
| 	c << std::endl << "[snapshot]" << std::endl; | ||||
| 	c << "id = " << this->id << std::endl; | ||||
| 	c << "time_captured = " << Slic3r::Utils::format_time_ISO8601Z(this->time_captured) << std::endl; | ||||
| 	c << "time_captured = " << Slic3r::Utils::iso_utc_timestamp(this->time_captured) << std::endl; | ||||
| 	c << "slic3r_version_captured = " << this->slic3r_version_captured.to_string() << std::endl; | ||||
| 	c << "comment = " << this->comment << std::endl; | ||||
| 	c << "reason = " << reason_string(this->reason) << std::endl; | ||||
|  | @ -365,7 +365,7 @@ const Snapshot&	SnapshotDB::take_snapshot(const AppConfig &app_config, Snapshot: | |||
| 	Snapshot snapshot; | ||||
| 	// Snapshot header.
 | ||||
| 	snapshot.time_captured 			 = Slic3r::Utils::get_current_time_utc(); | ||||
| 	snapshot.id 					 = Slic3r::Utils::format_time_ISO8601Z(snapshot.time_captured); | ||||
| 	snapshot.id 					 = Slic3r::Utils::iso_utc_timestamp(snapshot.time_captured); | ||||
| 	snapshot.slic3r_version_captured = Slic3r::SEMVER; | ||||
| 	snapshot.comment 				 = comment; | ||||
| 	snapshot.reason 				 = reason; | ||||
|  |  | |||
|  | @ -35,9 +35,14 @@ static wxString generate_html_row(const Config::Snapshot &snapshot, bool row_eve | |||
|     text += snapshot_active ? "#B3FFCB" : (row_even ? "#FFFFFF" : "#D5D5D5"); | ||||
|     text += "\">"; | ||||
|     text += "<td>"; | ||||
|      | ||||
|     static const constexpr char *LOCALE_TIME_FMT = "%x %X"; | ||||
|     wxString datetime = wxDateTime(snapshot.time_captured).Format(LOCALE_TIME_FMT); | ||||
|      | ||||
|     // Format the row header.
 | ||||
|     text += wxString("<font size=\"5\"><b>") + (snapshot_active ? _(L("Active")) + ": " : "") +  | ||||
|         Utils::format_local_date_time(snapshot.time_captured) + ": " + format_reason(snapshot.reason); | ||||
|     text += wxString("<font size=\"5\"><b>") + (snapshot_active ? _(L("Active")) + ": " : "") + | ||||
|             datetime + ": " + format_reason(snapshot.reason); | ||||
|      | ||||
|     if (! snapshot.comment.empty()) | ||||
|         text += " (" + wxString::FromUTF8(snapshot.comment.data()) + ")"; | ||||
|     text += "</b></font><br>"; | ||||
|  |  | |||
|  | @ -107,8 +107,8 @@ void GLTexture::Compressor::compress() | |||
|             break; | ||||
| 
 | ||||
|         // stb_dxt library, despite claiming that the needed size of the destination buffer is equal to (source buffer size)/4,
 | ||||
|         // crashes if doing so, so we start with twice the required size
 | ||||
|         level.compressed_data = std::vector<unsigned char>(level.w * level.h * 2, 0); | ||||
|         // crashes if doing so, requiring a minimum of 16 bytes and up to a third of the source buffer size, so we set the destination buffer initial size to be half the source buffer size
 | ||||
|         level.compressed_data = std::vector<unsigned char>(std::max((unsigned int)16, level.w * level.h * 2), 0); | ||||
|         int compressed_size = 0; | ||||
|         rygCompress(level.compressed_data.data(), level.src_data.data(), level.w, level.h, 1, compressed_size); | ||||
|         level.compressed_data.resize(compressed_size); | ||||
|  | @ -455,8 +455,7 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, ECo | |||
|         int lod_w = m_width; | ||||
|         int lod_h = m_height; | ||||
|         GLint level = 0; | ||||
|         // we do not need to generate all levels down to 1x1
 | ||||
|         while ((lod_w > 16) || (lod_h > 16)) | ||||
|         while ((lod_w > 1) || (lod_h > 1)) | ||||
|         { | ||||
|             ++level; | ||||
| 
 | ||||
|  | @ -600,8 +599,7 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, boo | |||
|         int lod_w = m_width; | ||||
|         int lod_h = m_height; | ||||
|         GLint level = 0; | ||||
|         // we do not need to generate all levels down to 1x1
 | ||||
|         while ((lod_w > 16) || (lod_h > 16)) | ||||
|         while ((lod_w > 1) || (lod_h > 1)) | ||||
|         { | ||||
|             ++level; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,3 +1,13 @@ | |||
| # TODO Add individual tests as executables in separate directories | ||||
| # add_subirectory(<testcase>) | ||||
| 
 | ||||
| # add_subirectory(<testcase>) | ||||
| find_package(GTest REQUIRED) | ||||
| 
 | ||||
| set(TEST_DATA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/data) | ||||
| file(TO_NATIVE_PATH "${TEST_DATA_DIR}" TEST_DATA_DIR) | ||||
| 
 | ||||
| add_library(test_common INTERFACE) | ||||
| target_compile_definitions(test_common INTERFACE TEST_DATA_DIR="${TEST_DATA_DIR}") | ||||
| target_link_libraries(test_common INTERFACE GTest::GTest GTest::Main) | ||||
| 
 | ||||
| add_subdirectory(timeutils) | ||||
|  |  | |||
							
								
								
									
										5
									
								
								tests/timeutils/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								tests/timeutils/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | |||
| add_executable(timeutils_tests timeutils_tests_main.cpp) | ||||
| target_link_libraries(timeutils_tests test_common libslic3r ${Boost_LIBRARIES} ${TBB_LIBRARIES} ${Boost_LIBRARIES}) | ||||
| 
 | ||||
| add_test(timeutils_tests timeutils_tests) | ||||
| #gtest_discover_tests(timeutils_tests TEST_PREFIX timeutils.) | ||||
							
								
								
									
										41
									
								
								tests/timeutils/timeutils_tests_main.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								tests/timeutils/timeutils_tests_main.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | |||
| #include <gtest/gtest.h> | ||||
| #include "libslic3r/Time.hpp" | ||||
| 
 | ||||
| #include <sstream> | ||||
| #include <iomanip> | ||||
| #include <locale> | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| void test_time_fmt(Slic3r::Utils::TimeFormat fmt) { | ||||
|     using namespace Slic3r::Utils; | ||||
|     time_t t = get_current_time_utc(); | ||||
|      | ||||
|     std::string tstr = time2str(t, TimeZone::local, fmt); | ||||
|     time_t parsedtime = str2time(tstr, TimeZone::local, fmt); | ||||
|     ASSERT_EQ(t, parsedtime); | ||||
|      | ||||
|     tstr = time2str(t, TimeZone::utc, fmt); | ||||
|     parsedtime = str2time(tstr, TimeZone::utc, fmt); | ||||
|     ASSERT_EQ(t, parsedtime); | ||||
|      | ||||
|     parsedtime = str2time("not valid string", TimeZone::local, fmt); | ||||
|     ASSERT_EQ(parsedtime, time_t(-1)); | ||||
|      | ||||
|     parsedtime = str2time("not valid string", TimeZone::utc, fmt); | ||||
|     ASSERT_EQ(parsedtime, time_t(-1)); | ||||
| } | ||||
| } | ||||
| 
 | ||||
| TEST(Timeutils, ISO8601Z) { | ||||
|     test_time_fmt(Slic3r::Utils::TimeFormat::iso8601Z); | ||||
| } | ||||
| 
 | ||||
| TEST(Timeutils, Slic3r_UTC_Time_Format) { | ||||
|     test_time_fmt(Slic3r::Utils::TimeFormat::gcode); | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char **argv) { | ||||
|     ::testing::InitGoogleTest(&argc, argv); | ||||
|     return RUN_ALL_TESTS(); | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 YuSanka
						YuSanka