Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/xs/src
diff options
context:
space:
mode:
authorbubnikv <bubnikv@gmail.com>2017-08-03 18:31:31 +0300
committerbubnikv <bubnikv@gmail.com>2017-08-03 18:31:31 +0300
commit138501872426ae1fc7023478dd1deba96d936ecf (patch)
tree74825b7caf247a6761d1cb0705edd16297e700ca /xs/src
parent31085fb1d70510e3d73c64c0b7fc7a394b6e6f72 (diff)
Unicode handling:
Removed the Perl dependencies on Encode, Encode::Locale and Unicode::Normalize. Added dependency on boost::locale. Added encode_path, decode_path, normalize_utf8 functions to Slic3r.xs Slic3r.xs has been made mostly utf8 safe by using the boost::nowide library, thanks to @alexrj for the idea. Simplified the encode_path / decode_path stuff: wxWidgets are unicode already, so there is no need to decode_path() from it. Perl / win32 interfacing is non-unicode, so decode_path() is executed on ARGV just at the beginning of the perl scripts.
Diffstat (limited to 'xs/src')
-rw-r--r--xs/src/admesh/connect.cpp (renamed from xs/src/admesh/connect.c)0
-rw-r--r--xs/src/admesh/normals.cpp (renamed from xs/src/admesh/normals.c)50
-rw-r--r--xs/src/admesh/shared.cpp (renamed from xs/src/admesh/shared.c)8
-rw-r--r--xs/src/admesh/stl.h8
-rw-r--r--xs/src/admesh/stl_io.cpp (renamed from xs/src/admesh/stl_io.c)13
-rw-r--r--xs/src/admesh/stlinit.cpp (renamed from xs/src/admesh/stlinit.c)6
-rw-r--r--xs/src/admesh/util.cpp (renamed from xs/src/admesh/util.c)4
-rw-r--r--xs/src/libslic3r/Format/AMF.cpp6
-rw-r--r--xs/src/libslic3r/Format/PRUS.cpp11
-rw-r--r--xs/src/libslic3r/Format/objparser.cpp8
-rw-r--r--xs/src/libslic3r/GCode.cpp32
-rw-r--r--xs/src/libslic3r/GCode.hpp4
-rw-r--r--xs/src/libslic3r/Model.cpp3
-rw-r--r--xs/src/libslic3r/SVG.cpp6
-rw-r--r--xs/src/libslic3r/Utils.hpp4
-rw-r--r--xs/src/libslic3r/utils.cpp64
16 files changed, 163 insertions, 64 deletions
diff --git a/xs/src/admesh/connect.c b/xs/src/admesh/connect.cpp
index e9129d007..e9129d007 100644
--- a/xs/src/admesh/connect.c
+++ b/xs/src/admesh/connect.cpp
diff --git a/xs/src/admesh/normals.c b/xs/src/admesh/normals.cpp
index 2832899fa..28b1c47b0 100644
--- a/xs/src/admesh/normals.c
+++ b/xs/src/admesh/normals.cpp
@@ -27,9 +27,13 @@
#include "stl.h"
-static void stl_reverse_facet(stl_file *stl, int facet_num);
-static void stl_reverse_vector(float v[]);
-int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag);
+static void stl_reverse_vector(float v[]) {
+ v[0] *= -1;
+ v[1] *= -1;
+ v[2] *= -1;
+}
+
+static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag);
static void
stl_reverse_facet(stl_file *stl, int facet_num) {
@@ -136,10 +140,8 @@ stl_fix_normal_directions(stl_file *stl) {
/* Reverse the neighboring facets if necessary. */
if(stl->neighbors_start[facet_num].which_vertex_not[j] > 2) {
/* If the facet has a neighbor that is -1, it means that edge isn't shared by another facet */
- if(stl->neighbors_start[facet_num].neighbor[j] != -1) {
- stl_reverse_facet
- (stl, stl->neighbors_start[facet_num].neighbor[j]);
- }
+ if(stl->neighbors_start[facet_num].neighbor[j] != -1)
+ stl_reverse_facet(stl, stl->neighbors_start[facet_num].neighbor[j]);
}
/* If this edge of the facet is connected: */
if(stl->neighbors_start[facet_num].neighbor[j] != -1) {
@@ -193,8 +195,7 @@ stl_fix_normal_directions(stl_file *stl) {
free(norm_sw);
}
-int
-stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag) {
+static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag) {
/* Returns 0 if the normal is within tolerance */
/* Returns 1 if the normal is not within tolerance, but direction is OK */
/* Returns 2 if the normal is not within tolerance and backwards */
@@ -259,26 +260,17 @@ stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag) {
return 4;
}
-static void
-stl_reverse_vector(float v[]) {
- v[0] *= -1;
- v[1] *= -1;
- v[2] *= -1;
-}
-
-
-void
-stl_calculate_normal(float normal[], stl_facet *facet) {
- float v1[3];
- float v2[3];
-
- v1[0] = facet->vertex[1].x - facet->vertex[0].x;
- v1[1] = facet->vertex[1].y - facet->vertex[0].y;
- v1[2] = facet->vertex[1].z - facet->vertex[0].z;
- v2[0] = facet->vertex[2].x - facet->vertex[0].x;
- v2[1] = facet->vertex[2].y - facet->vertex[0].y;
- v2[2] = facet->vertex[2].z - facet->vertex[0].z;
-
+void stl_calculate_normal(float normal[], stl_facet *facet) {
+ float v1[3] = {
+ facet->vertex[1].x - facet->vertex[0].x,
+ facet->vertex[1].y - facet->vertex[0].y,
+ facet->vertex[1].z - facet->vertex[0].z
+ };
+ float v2[3] = {
+ facet->vertex[2].x - facet->vertex[0].x,
+ facet->vertex[2].y - facet->vertex[0].y,
+ facet->vertex[2].z - facet->vertex[0].z
+ };
normal[0] = (float)((double)v1[1] * (double)v2[2]) - ((double)v1[2] * (double)v2[1]);
normal[1] = (float)((double)v1[2] * (double)v2[0]) - ((double)v1[0] * (double)v2[2]);
normal[2] = (float)((double)v1[0] * (double)v2[1]) - ((double)v1[1] * (double)v2[0]);
diff --git a/xs/src/admesh/shared.c b/xs/src/admesh/shared.cpp
index 56164e25f..8080f3574 100644
--- a/xs/src/admesh/shared.c
+++ b/xs/src/admesh/shared.cpp
@@ -23,6 +23,8 @@
#include <stdlib.h>
#include <string.h>
+#include <boost/nowide/cstdio.hpp>
+
#include "stl.h"
void
@@ -149,7 +151,7 @@ stl_write_off(stl_file *stl, char *file) {
if (stl->error) return;
/* Open the file */
- fp = fopen(file, "w");
+ fp = boost::nowide::fopen(file, "w");
if(fp == NULL) {
error_msg = (char*)
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
@@ -185,7 +187,7 @@ stl_write_vrml(stl_file *stl, char *file) {
if (stl->error) return;
/* Open the file */
- fp = fopen(file, "w");
+ fp = boost::nowide::fopen(file, "w");
if(fp == NULL) {
error_msg = (char*)
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
@@ -241,7 +243,7 @@ void stl_write_obj (stl_file *stl, char *file) {
if (stl->error) return;
/* Open the file */
- fp = fopen(file, "w");
+ fp = boost::nowide::fopen(file, "w");
if (fp == NULL) {
char* error_msg = (char*)malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", file);
diff --git a/xs/src/admesh/stl.h b/xs/src/admesh/stl.h
index 139983632..82c860636 100644
--- a/xs/src/admesh/stl.h
+++ b/xs/src/admesh/stl.h
@@ -32,10 +32,6 @@
#error "admesh works correctly on little endian machines only!"
#endif
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#define STL_MAX(A,B) ((A)>(B)? (A):(B))
#define STL_MIN(A,B) ((A)<(B)? (A):(B))
#define ABS(X) ((X) < 0 ? -(X) : (X))
@@ -223,8 +219,4 @@ extern void stl_clear_error(stl_file *stl);
extern int stl_get_error(stl_file *stl);
extern void stl_exit_on_error(stl_file *stl);
-#ifdef __cplusplus
-}
-#endif
-
#endif
diff --git a/xs/src/admesh/stl_io.c b/xs/src/admesh/stl_io.cpp
index 7d8e4eab8..f58d6b4f6 100644
--- a/xs/src/admesh/stl_io.c
+++ b/xs/src/admesh/stl_io.cpp
@@ -25,6 +25,8 @@
#include "stl.h"
#include "config.h"
+#include <boost/nowide/cstdio.hpp>
+
#if !defined(SEEK_SET)
#define SEEK_SET 0
#define SEEK_CUR 1
@@ -126,13 +128,12 @@ Normals fixed : %5d\n", stl->stats.normals_fixed);
void
stl_write_ascii(stl_file *stl, const char *file, const char *label) {
int i;
- FILE *fp;
char *error_msg;
if (stl->error) return;
/* Open the file */
- fp = fopen(file, "w");
+ FILE *fp = boost::nowide::fopen(file, "w");
if(fp == NULL) {
error_msg = (char*)
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
@@ -178,7 +179,7 @@ stl_print_neighbors(stl_file *stl, char *file) {
if (stl->error) return;
/* Open the file */
- fp = fopen(file, "w");
+ fp = boost::nowide::fopen(file, "w");
if(fp == NULL) {
error_msg = (char*)
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
@@ -212,7 +213,7 @@ stl_write_binary(stl_file *stl, const char *file, const char *label) {
if (stl->error) return;
/* Open the file */
- fp = fopen(file, "wb");
+ fp = boost::nowide::fopen(file, "wb");
if(fp == NULL) {
error_msg = (char*)
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
@@ -292,7 +293,7 @@ stl_write_quad_object(stl_file *stl, char *file) {
if (stl->error) return;
/* Open the file */
- fp = fopen(file, "w");
+ fp = boost::nowide::fopen(file, "w");
if(fp == NULL) {
error_msg = (char*)
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
@@ -360,7 +361,7 @@ stl_write_dxf(stl_file *stl, char *file, char *label) {
if (stl->error) return;
/* Open the file */
- fp = fopen(file, "w");
+ fp = boost::nowide::fopen(file, "w");
if(fp == NULL) {
error_msg = (char*)
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
diff --git a/xs/src/admesh/stlinit.c b/xs/src/admesh/stlinit.cpp
index 13f1f43af..f5110d394 100644
--- a/xs/src/admesh/stlinit.c
+++ b/xs/src/admesh/stlinit.cpp
@@ -26,6 +26,8 @@
#include <math.h>
#include <assert.h>
+#include <boost/nowide/cstdio.hpp>
+
#include "stl.h"
#ifndef SEEK_SET
@@ -62,7 +64,7 @@ stl_count_facets(stl_file *stl, const char *file) {
if (stl->error) return;
/* Open the file in binary mode first */
- stl->fp = fopen(file, "rb");
+ stl->fp = boost::nowide::fopen(file, "rb");
if(stl->fp == NULL) {
error_msg = (char*)
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
@@ -121,7 +123,7 @@ stl_count_facets(stl_file *stl, const char *file) {
/* Reopen the file in text mode (for getting correct newlines on Windows) */
// fix to silence a warning about unused return value.
// obviously if it fails we have problems....
- stl->fp = freopen(file, "r", stl->fp);
+ stl->fp = boost::nowide::freopen(file, "r", stl->fp);
// do another null check to be safe
if(stl->fp == NULL) {
diff --git a/xs/src/admesh/util.c b/xs/src/admesh/util.cpp
index cabb8a778..b0c31469d 100644
--- a/xs/src/admesh/util.c
+++ b/xs/src/admesh/util.cpp
@@ -186,7 +186,7 @@ static void calculate_normals(stl_file *stl) {
}
void stl_transform(stl_file *stl, float *trafo3x4) {
- int i_face, i_vertex, i, j;
+ int i_face, i_vertex;
if (stl->error)
return;
for (i_face = 0; i_face < stl->stats.number_of_facets; ++ i_face) {
@@ -404,7 +404,7 @@ static float get_volume(stl_file *stl) {
n = stl->facet_start[i].normal;
height = (n.x * p.x) + (n.y * p.y) + (n.z * p.z);
area = get_area(&stl->facet_start[i]);
- volume += (area * height) / 3.0;
+ volume += (area * height) / 3.0f;
}
return volume;
}
diff --git a/xs/src/libslic3r/Format/AMF.cpp b/xs/src/libslic3r/Format/AMF.cpp
index 9a9047eac..b8abf038b 100644
--- a/xs/src/libslic3r/Format/AMF.cpp
+++ b/xs/src/libslic3r/Format/AMF.cpp
@@ -3,6 +3,8 @@
#include <string>
#include <expat/expat.h>
+#include <boost/nowide/cstdio.hpp>
+
#include "../libslic3r.h"
#include "../Model.hpp"
#include "AMF.hpp"
@@ -480,7 +482,7 @@ bool load_amf(const char *path, Model *model)
return false;
}
- FILE *pFile = ::fopen(path, "rt");
+ FILE *pFile = boost::nowide::fopen(path, "rt");
if (pFile == nullptr) {
printf("Cannot open file %s\n", path);
return false;
@@ -522,7 +524,7 @@ bool load_amf(const char *path, Model *model)
bool store_amf(const char *path, Model *model)
{
- FILE *file = ::fopen(path, "wb");
+ FILE *file = boost::nowide::fopen(path, "wb");
if (file == nullptr)
return false;
diff --git a/xs/src/libslic3r/Format/PRUS.cpp b/xs/src/libslic3r/Format/PRUS.cpp
index 6b686d6ea..b7ef33774 100644
--- a/xs/src/libslic3r/Format/PRUS.cpp
+++ b/xs/src/libslic3r/Format/PRUS.cpp
@@ -2,6 +2,8 @@
#include <string.h>
+#include <boost/nowide/convert.hpp>
+
#include <wx/string.h>
#include <wx/wfstream.h>
#include <wx/zipstrm.h>
@@ -119,7 +121,14 @@ bool load_prus(const char *path, Model *model)
{
// To receive the content of the zipped 'scene.xml' file.
std::vector<char> scene_xml_data;
- wxFFileInputStream in(path);
+ wxFFileInputStream in(
+#ifdef WIN32
+ // On Windows, convert to a 16bit unicode string.
+ boost::nowide::widen(path).c_str()
+#else
+ path
+#endif
+ );
wxZipInputStream zip(in);
std::unique_ptr<wxZipEntry> entry;
size_t num_models = 0;
diff --git a/xs/src/libslic3r/Format/objparser.cpp b/xs/src/libslic3r/Format/objparser.cpp
index d8b86b703..88dfae695 100644
--- a/xs/src/libslic3r/Format/objparser.cpp
+++ b/xs/src/libslic3r/Format/objparser.cpp
@@ -1,6 +1,8 @@
#include <stdlib.h>
#include <string.h>
+#include <boost/nowide/cstdio.hpp>
+
#include "objparser.hpp"
namespace ObjParser {
@@ -318,7 +320,7 @@ static bool obj_parseline(const char *line, ObjData &data)
bool objparse(const char *path, ObjData &data)
{
- FILE *pFile = ::fopen(path, "rt");
+ FILE *pFile = boost::nowide::fopen(path, "rt");
if (pFile == 0)
return false;
@@ -446,7 +448,7 @@ bool loadvectornameidx(FILE *pFile, std::vector<T> &v)
bool objbinsave(const char *path, const ObjData &data)
{
- FILE *pFile = ::fopen(path, "wb");
+ FILE *pFile = boost::nowide::fopen(path, "wb");
if (pFile == 0)
return false;
@@ -471,7 +473,7 @@ bool objbinsave(const char *path, const ObjData &data)
bool objbinload(const char *path, ObjData &data)
{
- FILE *pFile = ::fopen(path, "rb");
+ FILE *pFile = boost::nowide::fopen(path, "rb");
if (pFile == 0)
return false;
diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp
index 5acda3a98..699621974 100644
--- a/xs/src/libslic3r/GCode.cpp
+++ b/xs/src/libslic3r/GCode.cpp
@@ -13,6 +13,10 @@
#include <boost/date_time/local_time/local_time.hpp>
#include <boost/foreach.hpp>
+#include <boost/nowide/iostream.hpp>
+#include <boost/nowide/cstdio.hpp>
+#include <boost/nowide/cstdlib.hpp>
+
#include "SVG.hpp"
#if 0
@@ -306,7 +310,33 @@ std::vector<std::pair<coordf_t, std::vector<GCode::LayerToPrint>>> GCode::collec
return layers_to_print;
}
-bool GCode::do_export(FILE *file, Print &print)
+bool GCode::do_export(Print *print, const char *path)
+{
+ // Remove the old g-code if it exists.
+ boost::nowide::remove(path);
+
+ std::string path_tmp(path);
+ path_tmp += ".tmp";
+
+ FILE *file = boost::nowide::fopen(path_tmp.c_str(), "wb");
+ if (file == nullptr)
+ return false;
+
+ bool result = this->_do_export(*print, file);
+ fclose(file);
+
+ if (result && boost::nowide::rename(path_tmp.c_str(), path) != 0) {
+ boost::nowide::cerr << "Failed to remove the output G-code file from " << path_tmp << " to " << path
+ << ". Is " << path_tmp << " locked?" << std::endl;
+ result = false;
+ }
+
+ if (! result)
+ boost::nowide::remove(path_tmp.c_str());
+ return result;
+}
+
+bool GCode::_do_export(Print &print, FILE *file)
{
// How many times will be change_layer() called?
// change_layer() in turn increments the progress bar status.
diff --git a/xs/src/libslic3r/GCode.hpp b/xs/src/libslic3r/GCode.hpp
index 51ab5eb84..ac0af3f2c 100644
--- a/xs/src/libslic3r/GCode.hpp
+++ b/xs/src/libslic3r/GCode.hpp
@@ -126,7 +126,7 @@ public:
{}
~GCode() {}
- bool do_export(FILE *file, Print &print);
+ bool do_export(Print *print, const char *path);
// Exported for the helper classes (OozePrevention, Wipe) and for the Perl binding for unit tests.
const Pointf& origin() const { return m_origin; }
@@ -146,6 +146,8 @@ public:
void apply_print_config(const PrintConfig &print_config);
protected:
+ bool _do_export(Print &print, FILE *file);
+
// Object and support extrusions of the same PrintObject at the same print_z.
struct LayerToPrint
{
diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp
index 5d0de1576..455469f8a 100644
--- a/xs/src/libslic3r/Model.cpp
+++ b/xs/src/libslic3r/Model.cpp
@@ -10,6 +10,7 @@
#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem.hpp>
+#include <boost/nowide/iostream.hpp>
namespace Slic3r {
@@ -739,7 +740,7 @@ void ModelObject::print_info() const
{
using namespace std;
cout << fixed;
- cout << "[" << boost::filesystem::path(this->input_file).filename().string() << "]" << endl;
+ boost::nowide::cout << "[" << boost::filesystem::path(this->input_file).filename().string() << "]" << endl;
TriangleMesh mesh = this->raw_mesh();
mesh.check_topology();
diff --git a/xs/src/libslic3r/SVG.cpp b/xs/src/libslic3r/SVG.cpp
index b8580fd5e..c94db8e74 100644
--- a/xs/src/libslic3r/SVG.cpp
+++ b/xs/src/libslic3r/SVG.cpp
@@ -1,6 +1,8 @@
#include "SVG.hpp"
#include <iostream>
+#include <boost/nowide/cstdio.hpp>
+
#define COORD(x) ((float)unscale((x))*10)
namespace Slic3r {
@@ -8,7 +10,7 @@ namespace Slic3r {
bool SVG::open(const char* afilename)
{
this->filename = afilename;
- this->f = fopen(afilename, "w");
+ this->f = boost::nowide::fopen(afilename, "w");
if (this->f == NULL)
return false;
fprintf(this->f,
@@ -27,7 +29,7 @@ bool SVG::open(const char* afilename, const BoundingBox &bbox, const coord_t bbo
this->filename = afilename;
this->origin = bbox.min - Point(bbox_offset, bbox_offset);
this->flipY = aflipY;
- this->f = ::fopen(afilename, "w");
+ this->f = boost::nowide::fopen(afilename, "w");
if (f == NULL)
return false;
float w = COORD(bbox.max.x - bbox.min.x + 2 * bbox_offset);
diff --git a/xs/src/libslic3r/Utils.hpp b/xs/src/libslic3r/Utils.hpp
index 0b6b87d28..45d1f2c51 100644
--- a/xs/src/libslic3r/Utils.hpp
+++ b/xs/src/libslic3r/Utils.hpp
@@ -6,6 +6,10 @@ namespace Slic3r {
extern void set_logging_level(unsigned int level);
extern void trace(unsigned int level, const char *message);
+extern std::string encode_path(const char *src);
+extern std::string decode_path(const char *src);
+extern std::string normalize_utf8_nfc(const char *src);
+
// Compute the next highest power of 2 of 32-bit v
// http://graphics.stanford.edu/~seander/bithacks.html
template<typename T>
diff --git a/xs/src/libslic3r/utils.cpp b/xs/src/libslic3r/utils.cpp
index 50db6f300..ea34fb18c 100644
--- a/xs/src/libslic3r/utils.cpp
+++ b/xs/src/libslic3r/utils.cpp
@@ -1,7 +1,21 @@
+#include <locale>
+
#include <boost/log/core.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/expressions.hpp>
+#include <boost/locale.hpp>
+
+#include <boost/nowide/integration/filesystem.hpp>
+#include <boost/nowide/convert.hpp>
+
+#ifdef WIN32
+extern "C" {
+__declspec(dllimport) int WideCharToMultiByte(unsigned int, unsigned long, wchar_t const *, int, char *, int, char const *, int *);
+__declspec(dllimport) int MultiByteToWideChar(unsigned int, unsigned long, char const *, int, wchar_t *, int);
+}
+#endif /* WIN32 */
+
namespace Slic3r {
static boost::log::trivial::severity_level logSeverity = boost::log::trivial::error;
@@ -30,9 +44,13 @@ void set_logging_level(unsigned int level)
}
// Force set_logging_level(<=error) after loading of the DLL.
-static struct SetLoggingLevelOnInit {
- SetLoggingLevelOnInit() { set_logging_level(1); }
-} g_SetLoggingLevelOnInit;
+// 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)
{
@@ -56,6 +74,46 @@ void trace(unsigned int level, const char *message)
(::boost::log::keywords::severity = severity)) << message;
}
+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 */
+}
+
+std::string decode_path(const char *src)
+{
+#ifdef WIN32
+ int len = 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("en_US.UTF-8");
+ return boost::locale::normalize(src, boost::locale::norm_nfc, locale_utf8);
+}
+
} // namespace Slic3r
#ifdef SLIC3R_HAS_BROKEN_CROAK