mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-11 16:57:53 -06:00
Merged branch 'dev_native' into lm_sla_supports_auto
Added igl library files
This commit is contained in:
commit
7681d00ee5
2865 changed files with 142806 additions and 22325 deletions
347
src/libslic3r/utils.cpp
Normal file
347
src/libslic3r/utils.cpp
Normal file
|
@ -0,0 +1,347 @@
|
|||
#include "Utils.hpp"
|
||||
#include "I18N.hpp"
|
||||
|
||||
#include <locale>
|
||||
#include <ctime>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <boost/log/core.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/log/expressions.hpp>
|
||||
|
||||
#include <boost/locale.hpp>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/date_time/local_time/local_time.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/nowide/integration/filesystem.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
|
||||
#include <tbb/task_scheduler_init.h>
|
||||
|
||||
#include <tbb/task_scheduler_init.h>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
static boost::log::trivial::severity_level logSeverity = boost::log::trivial::error;
|
||||
|
||||
void set_logging_level(unsigned int level)
|
||||
{
|
||||
switch (level) {
|
||||
// Report fatal errors only.
|
||||
case 0: logSeverity = boost::log::trivial::fatal; break;
|
||||
// Report fatal errors and errors.
|
||||
case 1: logSeverity = boost::log::trivial::error; break;
|
||||
// Report fatal errors, errors and warnings.
|
||||
case 2: logSeverity = boost::log::trivial::warning; break;
|
||||
// Report all errors, warnings and infos.
|
||||
case 3: logSeverity = boost::log::trivial::info; break;
|
||||
// Report all errors, warnings, infos and debugging.
|
||||
case 4: logSeverity = boost::log::trivial::debug; break;
|
||||
// Report everyting including fine level tracing information.
|
||||
default: logSeverity = boost::log::trivial::trace; break;
|
||||
}
|
||||
|
||||
boost::log::core::get()->set_filter
|
||||
(
|
||||
boost::log::trivial::severity >= logSeverity
|
||||
);
|
||||
}
|
||||
|
||||
// Force set_logging_level(<=error) after loading of the DLL.
|
||||
// Switch boost::filesystem to utf8.
|
||||
static struct RunOnInit {
|
||||
RunOnInit() {
|
||||
boost::nowide::nowide_filesystem();
|
||||
set_logging_level(1);
|
||||
}
|
||||
} g_RunOnInit;
|
||||
|
||||
void trace(unsigned int level, const char *message)
|
||||
{
|
||||
boost::log::trivial::severity_level severity = boost::log::trivial::trace;
|
||||
switch (level) {
|
||||
// Report fatal errors only.
|
||||
case 0: severity = boost::log::trivial::fatal; break;
|
||||
// Report fatal errors and errors.
|
||||
case 1: severity = boost::log::trivial::error; break;
|
||||
// Report fatal errors, errors and warnings.
|
||||
case 2: severity = boost::log::trivial::warning; break;
|
||||
// Report all errors, warnings and infos.
|
||||
case 3: severity = boost::log::trivial::info; break;
|
||||
// Report all errors, warnings, infos and debugging.
|
||||
case 4: severity = boost::log::trivial::debug; break;
|
||||
// Report everyting including fine level tracing information.
|
||||
default: severity = boost::log::trivial::trace; break;
|
||||
}
|
||||
|
||||
BOOST_LOG_STREAM_WITH_PARAMS(::boost::log::trivial::logger::get(),\
|
||||
(::boost::log::keywords::severity = severity)) << message;
|
||||
}
|
||||
|
||||
void disable_multi_threading()
|
||||
{
|
||||
// Disable parallelization so the Shiny profiler works
|
||||
static tbb::task_scheduler_init *tbb_init = nullptr;
|
||||
if (tbb_init == nullptr)
|
||||
tbb_init = new tbb::task_scheduler_init(1);
|
||||
}
|
||||
|
||||
static std::string g_var_dir;
|
||||
|
||||
void set_var_dir(const std::string &dir)
|
||||
{
|
||||
g_var_dir = dir;
|
||||
}
|
||||
|
||||
const std::string& var_dir()
|
||||
{
|
||||
return g_var_dir;
|
||||
}
|
||||
|
||||
std::string var(const std::string &file_name)
|
||||
{
|
||||
auto file = (boost::filesystem::path(g_var_dir) / file_name).make_preferred();
|
||||
return file.string();
|
||||
}
|
||||
|
||||
static std::string g_resources_dir;
|
||||
|
||||
void set_resources_dir(const std::string &dir)
|
||||
{
|
||||
g_resources_dir = dir;
|
||||
}
|
||||
|
||||
const std::string& resources_dir()
|
||||
{
|
||||
return g_resources_dir;
|
||||
}
|
||||
|
||||
static std::string g_local_dir;
|
||||
|
||||
void set_local_dir(const std::string &dir)
|
||||
{
|
||||
g_local_dir = dir;
|
||||
}
|
||||
|
||||
const std::string& localization_dir()
|
||||
{
|
||||
return g_local_dir;
|
||||
}
|
||||
|
||||
// Translate function callback, to call wxWidgets translate function to convert non-localized UTF8 string to a localized one.
|
||||
Slic3r::I18N::translate_fn_type Slic3r::I18N::translate_fn = nullptr;
|
||||
|
||||
static std::string g_data_dir;
|
||||
|
||||
void set_data_dir(const std::string &dir)
|
||||
{
|
||||
g_data_dir = dir;
|
||||
}
|
||||
|
||||
const std::string& data_dir()
|
||||
{
|
||||
return g_data_dir;
|
||||
}
|
||||
|
||||
|
||||
// borrowed from LVVM lib/Support/Windows/Path.inc
|
||||
int rename_file(const std::string &from, const std::string &to)
|
||||
{
|
||||
int ec = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// Convert to utf-16.
|
||||
std::wstring wide_from = boost::nowide::widen(from);
|
||||
std::wstring wide_to = boost::nowide::widen(to);
|
||||
|
||||
// Retry while we see recoverable errors.
|
||||
// System scanners (eg. indexer) might open the source file when it is written
|
||||
// and closed.
|
||||
bool TryReplace = true;
|
||||
|
||||
// This loop may take more than 2000 x 1ms to finish.
|
||||
for (int i = 0; i < 2000; ++ i) {
|
||||
if (i > 0)
|
||||
// Sleep 1ms
|
||||
::Sleep(1);
|
||||
if (TryReplace) {
|
||||
// Try ReplaceFile first, as it is able to associate a new data stream
|
||||
// with the destination even if the destination file is currently open.
|
||||
if (::ReplaceFileW(wide_to.data(), wide_from.data(), NULL, 0, NULL, NULL))
|
||||
return 0;
|
||||
DWORD ReplaceError = ::GetLastError();
|
||||
ec = -1; // ReplaceError
|
||||
// If ReplaceFileW returned ERROR_UNABLE_TO_MOVE_REPLACEMENT or
|
||||
// ERROR_UNABLE_TO_MOVE_REPLACEMENT_2, retry but only use MoveFileExW().
|
||||
if (ReplaceError == ERROR_UNABLE_TO_MOVE_REPLACEMENT ||
|
||||
ReplaceError == ERROR_UNABLE_TO_MOVE_REPLACEMENT_2) {
|
||||
TryReplace = false;
|
||||
continue;
|
||||
}
|
||||
// If ReplaceFileW returned ERROR_UNABLE_TO_REMOVE_REPLACED, retry
|
||||
// using ReplaceFileW().
|
||||
if (ReplaceError == ERROR_UNABLE_TO_REMOVE_REPLACED)
|
||||
continue;
|
||||
// We get ERROR_FILE_NOT_FOUND if the destination file is missing.
|
||||
// MoveFileEx can handle this case.
|
||||
if (ReplaceError != ERROR_ACCESS_DENIED && ReplaceError != ERROR_FILE_NOT_FOUND && ReplaceError != ERROR_SHARING_VIOLATION)
|
||||
break;
|
||||
}
|
||||
if (::MoveFileExW(wide_from.c_str(), wide_to.c_str(), MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING))
|
||||
return 0;
|
||||
DWORD MoveError = ::GetLastError();
|
||||
ec = -1; // MoveError
|
||||
if (MoveError != ERROR_ACCESS_DENIED && MoveError != ERROR_SHARING_VIOLATION)
|
||||
break;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
boost::nowide::remove(to.c_str());
|
||||
ec = boost::nowide::rename(from.c_str(), to.c_str());
|
||||
|
||||
#endif
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
int copy_file(const std::string &from, const std::string &to)
|
||||
{
|
||||
const boost::filesystem::path source(from);
|
||||
const boost::filesystem::path target(to);
|
||||
static const auto perms = boost::filesystem::owner_read | boost::filesystem::owner_write | boost::filesystem::group_read | boost::filesystem::others_read; // aka 644
|
||||
|
||||
// Make sure the file has correct permission both before and after we copy over it.
|
||||
try {
|
||||
if (boost::filesystem::exists(target))
|
||||
boost::filesystem::permissions(target, perms);
|
||||
boost::filesystem::copy_file(source, target, boost::filesystem::copy_option::overwrite_if_exists);
|
||||
boost::filesystem::permissions(target, perms);
|
||||
} catch (std::exception & /* ex */) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif /* WIN32 */
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// Encode an UTF-8 string to the local code page.
|
||||
std::string encode_path(const char *src)
|
||||
{
|
||||
#ifdef WIN32
|
||||
// Convert the source utf8 encoded string to a wide string.
|
||||
std::wstring wstr_src = boost::nowide::widen(src);
|
||||
if (wstr_src.length() == 0)
|
||||
return std::string();
|
||||
// Convert a wide string to a local code page.
|
||||
int size_needed = ::WideCharToMultiByte(0, 0, wstr_src.data(), (int)wstr_src.size(), nullptr, 0, nullptr, nullptr);
|
||||
std::string str_dst(size_needed, 0);
|
||||
::WideCharToMultiByte(0, 0, wstr_src.data(), (int)wstr_src.size(), const_cast<char*>(str_dst.data()), size_needed, nullptr, nullptr);
|
||||
return str_dst;
|
||||
#else /* WIN32 */
|
||||
return src;
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
// Encode an 8-bit string from a local code page to UTF-8.
|
||||
std::string decode_path(const char *src)
|
||||
{
|
||||
#ifdef WIN32
|
||||
int len = int(strlen(src));
|
||||
if (len == 0)
|
||||
return std::string();
|
||||
// Convert the string encoded using the local code page to a wide string.
|
||||
int size_needed = ::MultiByteToWideChar(0, 0, src, len, nullptr, 0);
|
||||
std::wstring wstr_dst(size_needed, 0);
|
||||
::MultiByteToWideChar(0, 0, src, len, const_cast<wchar_t*>(wstr_dst.data()), size_needed);
|
||||
// Convert a wide string to utf8.
|
||||
return boost::nowide::narrow(wstr_dst.c_str());
|
||||
#else /* WIN32 */
|
||||
return src;
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
std::string normalize_utf8_nfc(const char *src)
|
||||
{
|
||||
static std::locale locale_utf8(boost::locale::generator().generate(""));
|
||||
return boost::locale::normalize(src, boost::locale::norm_nfc, locale_utf8);
|
||||
}
|
||||
|
||||
namespace PerlUtils {
|
||||
// Get a file name including the extension.
|
||||
std::string path_to_filename(const char *src) { return boost::filesystem::path(src).filename().string(); }
|
||||
// Get a file name without the extension.
|
||||
std::string path_to_stem(const char *src) { return boost::filesystem::path(src).stem().string(); }
|
||||
// Get just the extension.
|
||||
std::string path_to_extension(const char *src) { return boost::filesystem::path(src).extension().string(); }
|
||||
// Get a directory without the trailing slash.
|
||||
std::string path_to_parent_path(const char *src) { return boost::filesystem::path(src).parent_path().string(); }
|
||||
};
|
||||
|
||||
std::string timestamp_str()
|
||||
{
|
||||
const auto now = boost::posix_time::second_clock::local_time();
|
||||
char buf[2048];
|
||||
sprintf(buf, "on %04d-%02d-%02d at %02d:%02d:%02d",
|
||||
// Local date in an ANSII format.
|
||||
int(now.date().year()), int(now.date().month()), int(now.date().day()),
|
||||
int(now.time_of_day().hours()), int(now.time_of_day().minutes()), int(now.time_of_day().seconds()));
|
||||
return buf;
|
||||
}
|
||||
|
||||
unsigned get_current_pid()
|
||||
{
|
||||
#ifdef WIN32
|
||||
return GetCurrentProcessId();
|
||||
#else
|
||||
return ::getpid();
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string xml_escape(std::string text)
|
||||
{
|
||||
std::string::size_type pos = 0;
|
||||
for (;;)
|
||||
{
|
||||
pos = text.find_first_of("\"\'&<>", pos);
|
||||
if (pos == std::string::npos)
|
||||
break;
|
||||
|
||||
std::string replacement;
|
||||
switch (text[pos])
|
||||
{
|
||||
case '\"': replacement = """; break;
|
||||
case '\'': replacement = "'"; break;
|
||||
case '&': replacement = "&"; break;
|
||||
case '<': replacement = "<"; break;
|
||||
case '>': replacement = ">"; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
text.replace(pos, 1, replacement);
|
||||
pos += replacement.size();
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
}; // namespace Slic3r
|
Loading…
Add table
Add a link
Reference in a new issue