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.
This commit is contained in:
parent
31085fb1d7
commit
1385018724
3
Build.PL
3
Build.PL
@ -8,8 +8,6 @@ use File::Spec;
|
|||||||
|
|
||||||
my %prereqs = qw(
|
my %prereqs = qw(
|
||||||
Devel::CheckLib 0
|
Devel::CheckLib 0
|
||||||
Encode 0
|
|
||||||
Encode::Locale 1.05
|
|
||||||
ExtUtils::MakeMaker 6.80
|
ExtUtils::MakeMaker 6.80
|
||||||
ExtUtils::ParseXS 3.22
|
ExtUtils::ParseXS 3.22
|
||||||
File::Basename 0
|
File::Basename 0
|
||||||
@ -24,7 +22,6 @@ my %prereqs = qw(
|
|||||||
IO::Scalar 0
|
IO::Scalar 0
|
||||||
threads 1.96
|
threads 1.96
|
||||||
Time::HiRes 0
|
Time::HiRes 0
|
||||||
Unicode::Normalize 0
|
|
||||||
);
|
);
|
||||||
my %recommends = qw(
|
my %recommends = qw(
|
||||||
Class::XSAccessor 0
|
Class::XSAccessor 0
|
||||||
|
@ -75,20 +75,10 @@ use Slic3r::Print::Simple;
|
|||||||
use Slic3r::Surface;
|
use Slic3r::Surface;
|
||||||
our $build = eval "use Slic3r::Build; 1";
|
our $build = eval "use Slic3r::Build; 1";
|
||||||
use Thread::Semaphore;
|
use Thread::Semaphore;
|
||||||
use Encode::Locale 1.05;
|
|
||||||
use Encode;
|
|
||||||
use Unicode::Normalize;
|
|
||||||
|
|
||||||
# Scaling between the float and integer coordinates.
|
# Scaling between the float and integer coordinates.
|
||||||
# Floats are in mm.
|
# Floats are in mm.
|
||||||
use constant SCALING_FACTOR => 0.000001;
|
use constant SCALING_FACTOR => 0.000001;
|
||||||
use constant LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER => 0.15;
|
|
||||||
|
|
||||||
# Following constants are used by the infill algorithms and integration tests.
|
|
||||||
# Resolution to simplify perimeters to. These constants are now used in C++ code only. Better to publish them to Perl from the C++ code.
|
|
||||||
# use constant RESOLUTION => 0.0125;
|
|
||||||
# use constant SCALED_RESOLUTION => RESOLUTION / SCALING_FACTOR;
|
|
||||||
use constant INFILL_OVERLAP_OVER_SPACING => 0.3;
|
|
||||||
|
|
||||||
# Keep track of threads we created. Perl worker threads shall not create further threads.
|
# Keep track of threads we created. Perl worker threads shall not create further threads.
|
||||||
my @threads = ();
|
my @threads = ();
|
||||||
@ -211,39 +201,6 @@ sub resume_all_threads {
|
|||||||
$pause_sema->up;
|
$pause_sema->up;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Convert a Unicode path to a file system locale.
|
|
||||||
# The encoding is (from Encode::Locale POD):
|
|
||||||
# Alias | Windows | Mac OS X | POSIX
|
|
||||||
# locale_fs | ANSI | UTF-8 | nl_langinfo
|
|
||||||
# where nl_langinfo is en-US.UTF-8 on a modern Linux as well.
|
|
||||||
# So this conversion seems to make the most sense on Windows.
|
|
||||||
sub encode_path {
|
|
||||||
my ($path) = @_;
|
|
||||||
|
|
||||||
# UTF8 encoding is not unique. Normalize the UTF8 string to make the file names unique.
|
|
||||||
# Unicode::Normalize::NFC() returns the Normalization Form C (formed by canonical decomposition followed by canonical composition).
|
|
||||||
$path = Unicode::Normalize::NFC($path);
|
|
||||||
$path = Encode::encode(locale_fs => $path);
|
|
||||||
|
|
||||||
return $path;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Convert a path coded by a file system locale to Unicode.
|
|
||||||
sub decode_path {
|
|
||||||
my ($path) = @_;
|
|
||||||
|
|
||||||
$path = Encode::decode(locale_fs => $path)
|
|
||||||
unless Encode::is_utf8($path);
|
|
||||||
|
|
||||||
# The filesystem might force a normalization form (like HFS+ does) so
|
|
||||||
# if we rely on the filename being comparable after the open() + readdir()
|
|
||||||
# roundtrip (like when creating and then selecting a preset), we need to
|
|
||||||
# restore our normalization form.
|
|
||||||
$path = Unicode::Normalize::NFC($path);
|
|
||||||
|
|
||||||
return $path;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Open a file by converting $filename to local file system locales.
|
# Open a file by converting $filename to local file system locales.
|
||||||
sub open {
|
sub open {
|
||||||
my ($fh, $mode, $filename) = @_;
|
my ($fh, $mode, $filename) = @_;
|
||||||
|
@ -101,7 +101,7 @@ sub OnInit {
|
|||||||
# Unix: ~/.Slic3r
|
# Unix: ~/.Slic3r
|
||||||
# Windows: "C:\Users\username\AppData\Roaming\Slic3r" or "C:\Documents and Settings\username\Application Data\Slic3r"
|
# Windows: "C:\Users\username\AppData\Roaming\Slic3r" or "C:\Documents and Settings\username\Application Data\Slic3r"
|
||||||
# Mac: "~/Library/Application Support/Slic3r"
|
# Mac: "~/Library/Application Support/Slic3r"
|
||||||
$datadir ||= Slic3r::decode_path(Wx::StandardPaths::Get->GetUserDataDir);
|
$datadir ||= Wx::StandardPaths::Get->GetUserDataDir;
|
||||||
my $enc_datadir = Slic3r::encode_path($datadir);
|
my $enc_datadir = Slic3r::encode_path($datadir);
|
||||||
Slic3r::debugf "Data directory: %s\n", $datadir;
|
Slic3r::debugf "Data directory: %s\n", $datadir;
|
||||||
|
|
||||||
@ -370,9 +370,8 @@ sub open_model {
|
|||||||
$dialog->Destroy;
|
$dialog->Destroy;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
my @input_files = map Slic3r::decode_path($_), $dialog->GetPaths;
|
my @input_files = $dialog->GetPaths;
|
||||||
$dialog->Destroy;
|
$dialog->Destroy;
|
||||||
|
|
||||||
return @input_files;
|
return @input_files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +286,7 @@ sub _load_stl {
|
|||||||
$dialog->Destroy;
|
$dialog->Destroy;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
my $input_file = Slic3r::decode_path($dialog->GetPaths);
|
my $input_file = $dialog->GetPaths;
|
||||||
$dialog->Destroy;
|
$dialog->Destroy;
|
||||||
|
|
||||||
my $model = Slic3r::Model->read_from_file($input_file);
|
my $model = Slic3r::Model->read_from_file($input_file);
|
||||||
|
@ -368,7 +368,7 @@ sub quick_slice {
|
|||||||
$dialog->Destroy;
|
$dialog->Destroy;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$input_file = Slic3r::decode_path($dialog->GetPaths);
|
$input_file = $dialog->GetPaths;
|
||||||
$dialog->Destroy;
|
$dialog->Destroy;
|
||||||
$qs_last_input_file = $input_file unless $params{export_svg};
|
$qs_last_input_file = $input_file unless $params{export_svg};
|
||||||
} else {
|
} else {
|
||||||
@ -428,7 +428,7 @@ sub quick_slice {
|
|||||||
$dlg->Destroy;
|
$dlg->Destroy;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$output_file = Slic3r::decode_path($dlg->GetPath);
|
$output_file = $dlg->GetPath;
|
||||||
$qs_last_output_file = $output_file unless $params{export_svg};
|
$qs_last_output_file = $output_file unless $params{export_svg};
|
||||||
$Slic3r::GUI::Settings->{_}{last_output_path} = dirname($output_file);
|
$Slic3r::GUI::Settings->{_}{last_output_path} = dirname($output_file);
|
||||||
wxTheApp->save_settings;
|
wxTheApp->save_settings;
|
||||||
@ -482,7 +482,7 @@ sub repair_stl {
|
|||||||
$dialog->Destroy;
|
$dialog->Destroy;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$input_file = Slic3r::decode_path($dialog->GetPaths);
|
$input_file = $dialog->GetPaths;
|
||||||
$dialog->Destroy;
|
$dialog->Destroy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,14 +495,14 @@ sub repair_stl {
|
|||||||
$dlg->Destroy;
|
$dlg->Destroy;
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
$output_file = Slic3r::decode_path($dlg->GetPath);
|
$output_file = $dlg->GetPath;
|
||||||
$dlg->Destroy;
|
$dlg->Destroy;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $tmesh = Slic3r::TriangleMesh->new;
|
my $tmesh = Slic3r::TriangleMesh->new;
|
||||||
$tmesh->ReadSTLFile(Slic3r::encode_path($input_file));
|
$tmesh->ReadSTLFile($input_file);
|
||||||
$tmesh->repair;
|
$tmesh->repair;
|
||||||
$tmesh->WriteOBJFile(Slic3r::encode_path($output_file));
|
$tmesh->WriteOBJFile($output_file);
|
||||||
Slic3r::GUI::show_info($self, "Your file was repaired.", "Repair");
|
Slic3r::GUI::show_info($self, "Your file was repaired.", "Repair");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,7 +529,7 @@ sub export_config {
|
|||||||
my $dlg = Wx::FileDialog->new($self, 'Save configuration as:', $dir, $filename,
|
my $dlg = Wx::FileDialog->new($self, 'Save configuration as:', $dir, $filename,
|
||||||
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||||
if ($dlg->ShowModal == wxID_OK) {
|
if ($dlg->ShowModal == wxID_OK) {
|
||||||
my $file = Slic3r::decode_path($dlg->GetPath);
|
my $file = $dlg->GetPath;
|
||||||
$Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file);
|
$Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file);
|
||||||
wxTheApp->save_settings;
|
wxTheApp->save_settings;
|
||||||
$last_config = $file;
|
$last_config = $file;
|
||||||
@ -548,7 +548,7 @@ sub load_config_file {
|
|||||||
my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', $dir, "config.ini",
|
my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', $dir, "config.ini",
|
||||||
'INI files (*.ini, *.gcode)|*.ini;*.INI;*.gcode;*.g', wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
'INI files (*.ini, *.gcode)|*.ini;*.INI;*.gcode;*.g', wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||||
return unless $dlg->ShowModal == wxID_OK;
|
return unless $dlg->ShowModal == wxID_OK;
|
||||||
$file = Slic3r::decode_path($dlg->GetPaths);
|
$file = $dlg->GetPaths;
|
||||||
$dlg->Destroy;
|
$dlg->Destroy;
|
||||||
}
|
}
|
||||||
for my $tab (values %{$self->{options_tabs}}) {
|
for my $tab (values %{$self->{options_tabs}}) {
|
||||||
@ -574,7 +574,7 @@ sub export_configbundle {
|
|||||||
my $dlg = Wx::FileDialog->new($self, 'Save presets bundle as:', $dir, $filename,
|
my $dlg = Wx::FileDialog->new($self, 'Save presets bundle as:', $dir, $filename,
|
||||||
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||||
if ($dlg->ShowModal == wxID_OK) {
|
if ($dlg->ShowModal == wxID_OK) {
|
||||||
my $file = Slic3r::decode_path($dlg->GetPath);
|
my $file = $dlg->GetPath;
|
||||||
$Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file);
|
$Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file);
|
||||||
wxTheApp->save_settings;
|
wxTheApp->save_settings;
|
||||||
|
|
||||||
@ -604,7 +604,7 @@ sub load_configbundle {
|
|||||||
my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', $dir, "config.ini",
|
my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', $dir, "config.ini",
|
||||||
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||||
return unless $dlg->ShowModal == wxID_OK;
|
return unless $dlg->ShowModal == wxID_OK;
|
||||||
$file = Slic3r::decode_path($dlg->GetPaths);
|
$file = $dlg->GetPaths;
|
||||||
$dlg->Destroy;
|
$dlg->Destroy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1408,7 +1408,7 @@ sub export_gcode {
|
|||||||
$dlg->Destroy;
|
$dlg->Destroy;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
my $path = Slic3r::decode_path($dlg->GetPath);
|
my $path = $dlg->GetPath;
|
||||||
$Slic3r::GUI::Settings->{_}{last_output_path} = dirname($path);
|
$Slic3r::GUI::Settings->{_}{last_output_path} = dirname($path);
|
||||||
wxTheApp->save_settings;
|
wxTheApp->save_settings;
|
||||||
$self->{export_gcode_output_file} = $path;
|
$self->{export_gcode_output_file} = $path;
|
||||||
@ -1574,7 +1574,7 @@ sub send_gcode {
|
|||||||
my $ua = LWP::UserAgent->new;
|
my $ua = LWP::UserAgent->new;
|
||||||
$ua->timeout(180);
|
$ua->timeout(180);
|
||||||
|
|
||||||
my $path = Slic3r::encode_path($self->{send_gcode_file});
|
my $enc_path = Slic3r::encode_path($self->{send_gcode_file});
|
||||||
my $res = $ua->post(
|
my $res = $ua->post(
|
||||||
"http://" . $self->{config}->octoprint_host . "/api/files/local",
|
"http://" . $self->{config}->octoprint_host . "/api/files/local",
|
||||||
Content_Type => 'form-data',
|
Content_Type => 'form-data',
|
||||||
@ -1582,7 +1582,7 @@ sub send_gcode {
|
|||||||
Content => [
|
Content => [
|
||||||
# OctoPrint doesn't like Windows paths so we use basename()
|
# OctoPrint doesn't like Windows paths so we use basename()
|
||||||
# Also, since we need to read from filesystem we process it through encode_path()
|
# Also, since we need to read from filesystem we process it through encode_path()
|
||||||
file => [ $path, basename($path) ],
|
file => [ $enc_path, basename($enc_path) ],
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1603,7 +1603,7 @@ sub export_stl {
|
|||||||
return if !@{$self->{objects}};
|
return if !@{$self->{objects}};
|
||||||
|
|
||||||
my $output_file = $self->_get_export_file('STL') or return;
|
my $output_file = $self->_get_export_file('STL') or return;
|
||||||
$self->{model}->store_stl(Slic3r::encode_path($output_file), 1);
|
$self->{model}->store_stl($output_file, 1);
|
||||||
$self->statusbar->SetStatusText("STL file exported to $output_file");
|
$self->statusbar->SetStatusText("STL file exported to $output_file");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1644,7 +1644,7 @@ sub export_object_stl {
|
|||||||
my $model_object = $self->{model}->objects->[$obj_idx];
|
my $model_object = $self->{model}->objects->[$obj_idx];
|
||||||
|
|
||||||
my $output_file = $self->_get_export_file('STL') or return;
|
my $output_file = $self->_get_export_file('STL') or return;
|
||||||
$model_object->mesh->write_binary(Slic3r::encode_path($output_file));
|
$model_object->mesh->write_binary($output_file);
|
||||||
$self->statusbar->SetStatusText("STL file exported to $output_file");
|
$self->statusbar->SetStatusText("STL file exported to $output_file");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1654,7 +1654,7 @@ sub export_amf {
|
|||||||
return if !@{$self->{objects}};
|
return if !@{$self->{objects}};
|
||||||
|
|
||||||
my $output_file = $self->_get_export_file('AMF') or return;
|
my $output_file = $self->_get_export_file('AMF') or return;
|
||||||
$self->{model}->store_amf(Slic3r::encode_path($output_file));
|
$self->{model}->store_amf($output_file);
|
||||||
$self->statusbar->SetStatusText("AMF file exported to $output_file");
|
$self->statusbar->SetStatusText("AMF file exported to $output_file");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1674,7 +1674,7 @@ sub _get_export_file {
|
|||||||
$dlg->Destroy;
|
$dlg->Destroy;
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
$output_file = Slic3r::decode_path($dlg->GetPath);
|
$output_file = $dlg->GetPath;
|
||||||
$dlg->Destroy;
|
$dlg->Destroy;
|
||||||
}
|
}
|
||||||
return $output_file;
|
return $output_file;
|
||||||
|
@ -112,8 +112,9 @@ sub new {
|
|||||||
my $res = Wx::MessageDialog->new($self, "Are you sure you want to delete the selected preset?", 'Delete Preset', wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION)->ShowModal;
|
my $res = Wx::MessageDialog->new($self, "Are you sure you want to delete the selected preset?", 'Delete Preset', wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION)->ShowModal;
|
||||||
return unless $res == wxID_YES;
|
return unless $res == wxID_YES;
|
||||||
# Delete the file.
|
# Delete the file.
|
||||||
my $path = Slic3r::encode_path($self->{presets}[$i]->file);
|
my $path = $self->{presets}[$i]->file;
|
||||||
if (-e $path && ! unlink $path) {
|
my $enc_path = Slic3r::encode_path($path);
|
||||||
|
if (-e $enc_path && ! unlink $enc_path) {
|
||||||
# Cannot delete the file, therefore the item will not be removed from the selection.
|
# Cannot delete the file, therefore the item will not be removed from the selection.
|
||||||
Slic3r::GUI::show_error($self, "Cannot delete file $path : $!");
|
Slic3r::GUI::show_error($self, "Cannot delete file $path : $!");
|
||||||
return;
|
return;
|
||||||
@ -255,7 +256,7 @@ sub select_preset {
|
|||||||
sub select_preset_by_name {
|
sub select_preset_by_name {
|
||||||
my ($self, $name) = @_;
|
my ($self, $name) = @_;
|
||||||
|
|
||||||
$name = Unicode::Normalize::NFC($name);
|
$name = Slic3r::normalize_utf8_nfc($name);
|
||||||
$self->select_preset(first { $self->{presets}[$_]->name eq $name } 0 .. $#{$self->{presets}});
|
$self->select_preset(first { $self->{presets}[$_]->name eq $name } 0 .. $#{$self->{presets}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,21 +75,9 @@ sub export_gcode {
|
|||||||
# output everything to a G-code file
|
# output everything to a G-code file
|
||||||
my $output_file = $self->output_filepath($params{output_file} // '');
|
my $output_file = $self->output_filepath($params{output_file} // '');
|
||||||
$self->status_cb->(90, "Exporting G-code" . ($output_file ? " to $output_file" : ""));
|
$self->status_cb->(90, "Exporting G-code" . ($output_file ? " to $output_file" : ""));
|
||||||
|
|
||||||
{
|
die "G-code export to " . $output_file . " failed\n"
|
||||||
# open output gcode file if we weren't supplied a file-handle
|
if ! Slic3r::GCode->new->do_export($self, $output_file);
|
||||||
my $tempfile = "$output_file.tmp";
|
|
||||||
my $gcode = Slic3r::GCode->new();
|
|
||||||
my $result = $gcode->do_export($self, Slic3r::encode_path($tempfile));
|
|
||||||
die $result . "\n" if ($result ne '');
|
|
||||||
my $i;
|
|
||||||
for ($i = 0; $i < 5; $i += 1) {
|
|
||||||
last if (rename Slic3r::encode_path($tempfile), Slic3r::encode_path($output_file));
|
|
||||||
# Wait for 1/4 seconds and try to rename once again.
|
|
||||||
select(undef, undef, undef, 0.25);
|
|
||||||
}
|
|
||||||
Slic3r::debugf "Failed to remove the output G-code file from $tempfile to $output_file. Is $tempfile locked?\n" if ($i == 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
# run post-processing scripts
|
# run post-processing scripts
|
||||||
if (@{$self->config->post_process}) {
|
if (@{$self->config->post_process}) {
|
||||||
|
14
slic3r.pl
14
slic3r.pl
@ -18,6 +18,9 @@ use Time::HiRes qw(gettimeofday tv_interval);
|
|||||||
$|++;
|
$|++;
|
||||||
binmode STDOUT, ':utf8';
|
binmode STDOUT, ':utf8';
|
||||||
|
|
||||||
|
# Convert all parameters from the local code page to utf8 on Windows.
|
||||||
|
@ARGV = map Slic3r::decode_path($_), @ARGV if $^O eq 'MSWin32';
|
||||||
|
|
||||||
our %opt = ();
|
our %opt = ();
|
||||||
my %cli_options = ();
|
my %cli_options = ();
|
||||||
{
|
{
|
||||||
@ -65,7 +68,6 @@ my %cli_options = ();
|
|||||||
my @external_configs = ();
|
my @external_configs = ();
|
||||||
if ($opt{load}) {
|
if ($opt{load}) {
|
||||||
foreach my $configfile (@{$opt{load}}) {
|
foreach my $configfile (@{$opt{load}}) {
|
||||||
$configfile = Slic3r::decode_path($configfile);
|
|
||||||
if (-e $configfile) {
|
if (-e $configfile) {
|
||||||
push @external_configs, Slic3r::Config->load($configfile);
|
push @external_configs, Slic3r::Config->load($configfile);
|
||||||
} elsif (-e "$FindBin::Bin/$configfile") {
|
} elsif (-e "$FindBin::Bin/$configfile") {
|
||||||
@ -102,7 +104,7 @@ my $gui;
|
|||||||
if ((!@ARGV || $opt{gui}) && !$opt{save} && eval "require Slic3r::GUI; 1") {
|
if ((!@ARGV || $opt{gui}) && !$opt{save} && eval "require Slic3r::GUI; 1") {
|
||||||
{
|
{
|
||||||
no warnings 'once';
|
no warnings 'once';
|
||||||
$Slic3r::GUI::datadir = Slic3r::decode_path($opt{datadir} // '');
|
$Slic3r::GUI::datadir = $opt{datadir} // '';
|
||||||
$Slic3r::GUI::no_controller = $opt{no_controller};
|
$Slic3r::GUI::no_controller = $opt{no_controller};
|
||||||
$Slic3r::GUI::no_plater = $opt{no_plater};
|
$Slic3r::GUI::no_plater = $opt{no_plater};
|
||||||
$Slic3r::GUI::autosave = $opt{autosave};
|
$Slic3r::GUI::autosave = $opt{autosave};
|
||||||
@ -111,7 +113,7 @@ if ((!@ARGV || $opt{gui}) && !$opt{save} && eval "require Slic3r::GUI; 1") {
|
|||||||
setlocale(LC_NUMERIC, 'C');
|
setlocale(LC_NUMERIC, 'C');
|
||||||
$gui->{mainframe}->load_config_file($_) for @{$opt{load}};
|
$gui->{mainframe}->load_config_file($_) for @{$opt{load}};
|
||||||
$gui->{mainframe}->load_config($cli_config);
|
$gui->{mainframe}->load_config($cli_config);
|
||||||
my @input_files = map Slic3r::decode_path($_), @ARGV;
|
my @input_files = @ARGV;
|
||||||
$gui->{mainframe}{plater}->load_files(\@input_files) unless $opt{no_plater};
|
$gui->{mainframe}{plater}->load_files(\@input_files) unless $opt{no_plater};
|
||||||
$gui->MainLoop;
|
$gui->MainLoop;
|
||||||
exit;
|
exit;
|
||||||
@ -123,7 +125,6 @@ if (@ARGV) { # slicing from command line
|
|||||||
|
|
||||||
if ($opt{repair}) {
|
if ($opt{repair}) {
|
||||||
foreach my $file (@ARGV) {
|
foreach my $file (@ARGV) {
|
||||||
$file = Slic3r::decode_path($file);
|
|
||||||
die "Repair is currently supported only on STL files\n"
|
die "Repair is currently supported only on STL files\n"
|
||||||
if $file !~ /\.[sS][tT][lL]$/;
|
if $file !~ /\.[sS][tT][lL]$/;
|
||||||
|
|
||||||
@ -139,7 +140,6 @@ if (@ARGV) { # slicing from command line
|
|||||||
|
|
||||||
if ($opt{cut}) {
|
if ($opt{cut}) {
|
||||||
foreach my $file (@ARGV) {
|
foreach my $file (@ARGV) {
|
||||||
$file = Slic3r::decode_path($file);
|
|
||||||
my $model = Slic3r::Model->read_from_file($file);
|
my $model = Slic3r::Model->read_from_file($file);
|
||||||
my $mesh = $model->mesh;
|
my $mesh = $model->mesh;
|
||||||
$mesh->translate(0, 0, -$mesh->bounding_box->z_min);
|
$mesh->translate(0, 0, -$mesh->bounding_box->z_min);
|
||||||
@ -158,7 +158,6 @@ if (@ARGV) { # slicing from command line
|
|||||||
|
|
||||||
if ($opt{split}) {
|
if ($opt{split}) {
|
||||||
foreach my $file (@ARGV) {
|
foreach my $file (@ARGV) {
|
||||||
$file = Slic3r::decode_path($file);
|
|
||||||
my $model = Slic3r::Model->read_from_file($file);
|
my $model = Slic3r::Model->read_from_file($file);
|
||||||
my $mesh = $model->mesh;
|
my $mesh = $model->mesh;
|
||||||
$mesh->repair;
|
$mesh->repair;
|
||||||
@ -167,14 +166,13 @@ if (@ARGV) { # slicing from command line
|
|||||||
foreach my $new_mesh (@{$mesh->split}) {
|
foreach my $new_mesh (@{$mesh->split}) {
|
||||||
my $output_file = sprintf '%s_%02d.stl', $file, ++$part_count;
|
my $output_file = sprintf '%s_%02d.stl', $file, ++$part_count;
|
||||||
printf "Writing to %s\n", basename($output_file);
|
printf "Writing to %s\n", basename($output_file);
|
||||||
$new_mesh->write_binary(Slic3r::encode_path($output_file));
|
$new_mesh->write_binary($output_file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (my $input_file = shift @ARGV) {
|
while (my $input_file = shift @ARGV) {
|
||||||
$input_file = Slic3r::decode_path($input_file);
|
|
||||||
my $model;
|
my $model;
|
||||||
if ($opt{merge}) {
|
if ($opt{merge}) {
|
||||||
my @models = map Slic3r::Model->read_from_file($_), $input_file, (splice @ARGV, 0);
|
my @models = map Slic3r::Model->read_from_file($_), $input_file, (splice @ARGV, 0);
|
||||||
|
@ -14,6 +14,9 @@ use Getopt::Long qw(:config no_auto_abbrev);
|
|||||||
use Slic3r;
|
use Slic3r;
|
||||||
$|++;
|
$|++;
|
||||||
|
|
||||||
|
# Convert all parameters from the local code page to utf8 on Windows.
|
||||||
|
@ARGV = map Slic3r::decode_path($_), @ARGV if $^O eq 'MSWin32';
|
||||||
|
|
||||||
my %opt = ();
|
my %opt = ();
|
||||||
{
|
{
|
||||||
my %options = (
|
my %options = (
|
||||||
@ -25,12 +28,12 @@ my %opt = ();
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
my $model = Slic3r::Model->load_amf(Slic3r::encode_path($ARGV[0]));
|
my $model = Slic3r::Model->load_amf($ARGV[0]);
|
||||||
my $output_file = $ARGV[0];
|
my $output_file = $ARGV[0];
|
||||||
$output_file =~ s/\.[aA][mM][fF](?:\.[xX][mM][lL])?$/\.stl/;
|
$output_file =~ s/\.[aA][mM][fF](?:\.[xX][mM][lL])?$/\.stl/;
|
||||||
|
|
||||||
printf "Writing to %s\n", basename($output_file);
|
printf "Writing to %s\n", basename($output_file);
|
||||||
$model->store_stl(Slic3r::encode_path($output_file), binary => !$opt{ascii});
|
$model->store_stl($output_file, binary => !$opt{ascii});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ $|++;
|
|||||||
$ARGV[0] or usage(1);
|
$ARGV[0] or usage(1);
|
||||||
|
|
||||||
if (-e $ARGV[0]) {
|
if (-e $ARGV[0]) {
|
||||||
my $model = Slic3r::Model->load_stl(Slic3r::encode_path($ARGV[0]), basename($ARGV[0]));
|
my $model = Slic3r::Model->load_stl($ARGV[0], basename($ARGV[0]));
|
||||||
$model->objects->[0]->add_instance(offset => Slic3r::Pointf->new(0,0));
|
$model->objects->[0]->add_instance(offset => Slic3r::Pointf->new(0,0));
|
||||||
my $mesh = $model->mesh;
|
my $mesh = $model->mesh;
|
||||||
$mesh->repair;
|
$mesh->repair;
|
||||||
@ -27,7 +27,7 @@ if (-e $ARGV[0]) {
|
|||||||
exit 0;
|
exit 0;
|
||||||
} elsif ((my $model = Slic3r::Test::model($ARGV[0]))) {
|
} elsif ((my $model = Slic3r::Test::model($ARGV[0]))) {
|
||||||
$ARGV[1] or die "Missing writeable destination as second argument\n";
|
$ARGV[1] or die "Missing writeable destination as second argument\n";
|
||||||
$model->store_stl(Slic3r::encode_path($ARGV[1]), 1);
|
$model->store_stl($ARGV[1], 1);
|
||||||
printf "Model $ARGV[0] written to $ARGV[1]\n";
|
printf "Model $ARGV[0] written to $ARGV[1]\n";
|
||||||
exit 0;
|
exit 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -25,7 +25,7 @@ my %opt = ();
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
my $model = Slic3r::Model->load_stl(Slic3r::encode_path($ARGV[0]), basename($ARGV[0]));
|
my $model = Slic3r::Model->load_stl($ARGV[0], basename($ARGV[0]));
|
||||||
my $basename = $ARGV[0];
|
my $basename = $ARGV[0];
|
||||||
$basename =~ s/\.[sS][tT][lL]$//;
|
$basename =~ s/\.[sS][tT][lL]$//;
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ my %opt = ();
|
|||||||
|
|
||||||
my $output_file = sprintf '%s_%02d.stl', $basename, ++$part_count;
|
my $output_file = sprintf '%s_%02d.stl', $basename, ++$part_count;
|
||||||
printf "Writing to %s\n", basename($output_file);
|
printf "Writing to %s\n", basename($output_file);
|
||||||
$new_model->store_stl(Slic3r::encode_path($output_file), !$opt{ascii});
|
$new_model->store_stl($output_file, !$opt{ascii});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ my %opt = ();
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
my @models = map Slic3r::Model->load_stl(Slic3r::encode_path($_), basename($_)), @ARGV;
|
my @models = map Slic3r::Model->load_stl($_, basename($_)), @ARGV;
|
||||||
my $output_file = $ARGV[0];
|
my $output_file = $ARGV[0];
|
||||||
$output_file =~ s/\.[sS][tT][lL]$/.amf.xml/;
|
$output_file =~ s/\.[sS][tT][lL]$/.amf.xml/;
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ my %opt = ();
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf "Writing to %s\n", basename($output_file);
|
printf "Writing to %s\n", basename($output_file);
|
||||||
$new_model->store_amf(Slic3r::encode_path($output_file));
|
$new_model->store_amf($output_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -129,11 +129,11 @@ if (defined $ENV{BOOST_LIBRARYDIR}) {
|
|||||||
|
|
||||||
# In order to generate the -l switches we need to know how Boost libraries are named
|
# In order to generate the -l switches we need to know how Boost libraries are named
|
||||||
my $have_boost = 0;
|
my $have_boost = 0;
|
||||||
my @boost_libraries = qw(system thread filesystem log); # we need these
|
my @boost_libraries = qw(system thread filesystem locale log); # we need these
|
||||||
|
|
||||||
if (!$ENV{SLIC3R_STATIC}) {
|
if (!$ENV{SLIC3R_STATIC}) {
|
||||||
# Dynamic linking of boost libraries.
|
# Dynamic linking of boost libraries.
|
||||||
push @cflags, qw(-DBOOST_LOG_DYN_LINK);
|
push @cflags, qw(-DBOOST_LOG_DYN_LINK -DBOOST_LOCALE_DYN_LINK);
|
||||||
if (! $mswin) {
|
if (! $mswin) {
|
||||||
# Check without explicit lib path (works on Linux and OSX).
|
# Check without explicit lib path (works on Linux and OSX).
|
||||||
$have_boost = 1
|
$have_boost = 1
|
||||||
@ -193,10 +193,10 @@ path through the BOOST_DIR environment variable:
|
|||||||
Or you may specify BOOST_INCLUDEDIR and BOOST_LIBRARYDIR separatly, which
|
Or you may specify BOOST_INCLUDEDIR and BOOST_LIBRARYDIR separatly, which
|
||||||
is handy, if you have built Boost libraries with mutliple settings.
|
is handy, if you have built Boost libraries with mutliple settings.
|
||||||
|
|
||||||
Following boost libraries are needed by Slic3r Prusa Edition: system, filesystem, thread, log.
|
Following boost libraries are needed by Slic3r Prusa Edition: system, filesystem, thread, locale, log.
|
||||||
|
|
||||||
On Debian, you need to run
|
On Debian, you need to run
|
||||||
sudo apt-get install libboost-thread-dev libboost-system-dev libboost-filesystem-dev libboost-log-dev
|
sudo apt-get install libboost-thread-dev libboost-system-dev libboost-filesystem-dev libboost-locale-dev libboost-log-dev
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
12
xs/MANIFEST
12
xs/MANIFEST
@ -1,13 +1,13 @@
|
|||||||
Build.PL
|
Build.PL
|
||||||
lib/Slic3r/XS.pm
|
lib/Slic3r/XS.pm
|
||||||
MANIFEST This list of files
|
MANIFEST This list of files
|
||||||
src/admesh/connect.c
|
src/admesh/connect.cpp
|
||||||
src/admesh/normals.c
|
src/admesh/normals.cpp
|
||||||
src/admesh/shared.c
|
src/admesh/shared.cpp
|
||||||
src/admesh/stl.h
|
src/admesh/stl.h
|
||||||
src/admesh/stl_io.c
|
src/admesh/stl_io.cpp
|
||||||
src/admesh/stlinit.c
|
src/admesh/stlinit.cpp
|
||||||
src/admesh/util.c
|
src/admesh/util.cpp
|
||||||
src/boost/nowide/args.hpp
|
src/boost/nowide/args.hpp
|
||||||
src/boost/nowide/cenv.hpp
|
src/boost/nowide/cenv.hpp
|
||||||
src/boost/nowide/config.hpp
|
src/boost/nowide/config.hpp
|
||||||
|
@ -27,9 +27,13 @@
|
|||||||
|
|
||||||
#include "stl.h"
|
#include "stl.h"
|
||||||
|
|
||||||
static void stl_reverse_facet(stl_file *stl, int facet_num);
|
static void stl_reverse_vector(float v[]) {
|
||||||
static void stl_reverse_vector(float v[]);
|
v[0] *= -1;
|
||||||
int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag);
|
v[1] *= -1;
|
||||||
|
v[2] *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stl_reverse_facet(stl_file *stl, int facet_num) {
|
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. */
|
/* Reverse the neighboring facets if necessary. */
|
||||||
if(stl->neighbors_start[facet_num].which_vertex_not[j] > 2) {
|
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 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) {
|
if(stl->neighbors_start[facet_num].neighbor[j] != -1)
|
||||||
stl_reverse_facet
|
stl_reverse_facet(stl, stl->neighbors_start[facet_num].neighbor[j]);
|
||||||
(stl, stl->neighbors_start[facet_num].neighbor[j]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* If this edge of the facet is connected: */
|
/* If this edge of the facet is connected: */
|
||||||
if(stl->neighbors_start[facet_num].neighbor[j] != -1) {
|
if(stl->neighbors_start[facet_num].neighbor[j] != -1) {
|
||||||
@ -193,8 +195,7 @@ stl_fix_normal_directions(stl_file *stl) {
|
|||||||
free(norm_sw);
|
free(norm_sw);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag) {
|
||||||
stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag) {
|
|
||||||
/* Returns 0 if the normal is within tolerance */
|
/* Returns 0 if the normal is within tolerance */
|
||||||
/* Returns 1 if the normal is not within tolerance, but direction is OK */
|
/* Returns 1 if the normal is not within tolerance, but direction is OK */
|
||||||
/* Returns 2 if the normal is not within tolerance and backwards */
|
/* 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;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void stl_calculate_normal(float normal[], stl_facet *facet) {
|
||||||
stl_reverse_vector(float v[]) {
|
float v1[3] = {
|
||||||
v[0] *= -1;
|
facet->vertex[1].x - facet->vertex[0].x,
|
||||||
v[1] *= -1;
|
facet->vertex[1].y - facet->vertex[0].y,
|
||||||
v[2] *= -1;
|
facet->vertex[1].z - facet->vertex[0].z
|
||||||
}
|
};
|
||||||
|
float v2[3] = {
|
||||||
|
facet->vertex[2].x - facet->vertex[0].x,
|
||||||
void
|
facet->vertex[2].y - facet->vertex[0].y,
|
||||||
stl_calculate_normal(float normal[], stl_facet *facet) {
|
facet->vertex[2].z - facet->vertex[0].z
|
||||||
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;
|
|
||||||
|
|
||||||
normal[0] = (float)((double)v1[1] * (double)v2[2]) - ((double)v1[2] * (double)v2[1]);
|
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[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]);
|
normal[2] = (float)((double)v1[0] * (double)v2[1]) - ((double)v1[1] * (double)v2[0]);
|
@ -23,6 +23,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <boost/nowide/cstdio.hpp>
|
||||||
|
|
||||||
#include "stl.h"
|
#include "stl.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -149,7 +151,7 @@ stl_write_off(stl_file *stl, char *file) {
|
|||||||
if (stl->error) return;
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
fp = fopen(file, "w");
|
fp = boost::nowide::fopen(file, "w");
|
||||||
if(fp == NULL) {
|
if(fp == NULL) {
|
||||||
error_msg = (char*)
|
error_msg = (char*)
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
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;
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
fp = fopen(file, "w");
|
fp = boost::nowide::fopen(file, "w");
|
||||||
if(fp == NULL) {
|
if(fp == NULL) {
|
||||||
error_msg = (char*)
|
error_msg = (char*)
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
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;
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
fp = fopen(file, "w");
|
fp = boost::nowide::fopen(file, "w");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
char* error_msg = (char*)malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
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);
|
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", file);
|
@ -32,10 +32,6 @@
|
|||||||
#error "admesh works correctly on little endian machines only!"
|
#error "admesh works correctly on little endian machines only!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define STL_MAX(A,B) ((A)>(B)? (A):(B))
|
#define STL_MAX(A,B) ((A)>(B)? (A):(B))
|
||||||
#define STL_MIN(A,B) ((A)<(B)? (A):(B))
|
#define STL_MIN(A,B) ((A)<(B)? (A):(B))
|
||||||
#define ABS(X) ((X) < 0 ? -(X) : (X))
|
#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 int stl_get_error(stl_file *stl);
|
||||||
extern void stl_exit_on_error(stl_file *stl);
|
extern void stl_exit_on_error(stl_file *stl);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
#include "stl.h"
|
#include "stl.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <boost/nowide/cstdio.hpp>
|
||||||
|
|
||||||
#if !defined(SEEK_SET)
|
#if !defined(SEEK_SET)
|
||||||
#define SEEK_SET 0
|
#define SEEK_SET 0
|
||||||
#define SEEK_CUR 1
|
#define SEEK_CUR 1
|
||||||
@ -126,13 +128,12 @@ Normals fixed : %5d\n", stl->stats.normals_fixed);
|
|||||||
void
|
void
|
||||||
stl_write_ascii(stl_file *stl, const char *file, const char *label) {
|
stl_write_ascii(stl_file *stl, const char *file, const char *label) {
|
||||||
int i;
|
int i;
|
||||||
FILE *fp;
|
|
||||||
char *error_msg;
|
char *error_msg;
|
||||||
|
|
||||||
if (stl->error) return;
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
fp = fopen(file, "w");
|
FILE *fp = boost::nowide::fopen(file, "w");
|
||||||
if(fp == NULL) {
|
if(fp == NULL) {
|
||||||
error_msg = (char*)
|
error_msg = (char*)
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
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;
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
fp = fopen(file, "w");
|
fp = boost::nowide::fopen(file, "w");
|
||||||
if(fp == NULL) {
|
if(fp == NULL) {
|
||||||
error_msg = (char*)
|
error_msg = (char*)
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
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;
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
fp = fopen(file, "wb");
|
fp = boost::nowide::fopen(file, "wb");
|
||||||
if(fp == NULL) {
|
if(fp == NULL) {
|
||||||
error_msg = (char*)
|
error_msg = (char*)
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
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;
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
fp = fopen(file, "w");
|
fp = boost::nowide::fopen(file, "w");
|
||||||
if(fp == NULL) {
|
if(fp == NULL) {
|
||||||
error_msg = (char*)
|
error_msg = (char*)
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
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;
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
fp = fopen(file, "w");
|
fp = boost::nowide::fopen(file, "w");
|
||||||
if(fp == NULL) {
|
if(fp == NULL) {
|
||||||
error_msg = (char*)
|
error_msg = (char*)
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
@ -26,6 +26,8 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <boost/nowide/cstdio.hpp>
|
||||||
|
|
||||||
#include "stl.h"
|
#include "stl.h"
|
||||||
|
|
||||||
#ifndef SEEK_SET
|
#ifndef SEEK_SET
|
||||||
@ -62,7 +64,7 @@ stl_count_facets(stl_file *stl, const char *file) {
|
|||||||
if (stl->error) return;
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Open the file in binary mode first */
|
/* Open the file in binary mode first */
|
||||||
stl->fp = fopen(file, "rb");
|
stl->fp = boost::nowide::fopen(file, "rb");
|
||||||
if(stl->fp == NULL) {
|
if(stl->fp == NULL) {
|
||||||
error_msg = (char*)
|
error_msg = (char*)
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
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) */
|
/* Reopen the file in text mode (for getting correct newlines on Windows) */
|
||||||
// fix to silence a warning about unused return value.
|
// fix to silence a warning about unused return value.
|
||||||
// obviously if it fails we have problems....
|
// 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
|
// do another null check to be safe
|
||||||
if(stl->fp == NULL) {
|
if(stl->fp == NULL) {
|
@ -186,7 +186,7 @@ static void calculate_normals(stl_file *stl) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void stl_transform(stl_file *stl, float *trafo3x4) {
|
void stl_transform(stl_file *stl, float *trafo3x4) {
|
||||||
int i_face, i_vertex, i, j;
|
int i_face, i_vertex;
|
||||||
if (stl->error)
|
if (stl->error)
|
||||||
return;
|
return;
|
||||||
for (i_face = 0; i_face < stl->stats.number_of_facets; ++ i_face) {
|
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;
|
n = stl->facet_start[i].normal;
|
||||||
height = (n.x * p.x) + (n.y * p.y) + (n.z * p.z);
|
height = (n.x * p.x) + (n.y * p.y) + (n.z * p.z);
|
||||||
area = get_area(&stl->facet_start[i]);
|
area = get_area(&stl->facet_start[i]);
|
||||||
volume += (area * height) / 3.0;
|
volume += (area * height) / 3.0f;
|
||||||
}
|
}
|
||||||
return volume;
|
return volume;
|
||||||
}
|
}
|
@ -3,6 +3,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <expat/expat.h>
|
#include <expat/expat.h>
|
||||||
|
|
||||||
|
#include <boost/nowide/cstdio.hpp>
|
||||||
|
|
||||||
#include "../libslic3r.h"
|
#include "../libslic3r.h"
|
||||||
#include "../Model.hpp"
|
#include "../Model.hpp"
|
||||||
#include "AMF.hpp"
|
#include "AMF.hpp"
|
||||||
@ -480,7 +482,7 @@ bool load_amf(const char *path, Model *model)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *pFile = ::fopen(path, "rt");
|
FILE *pFile = boost::nowide::fopen(path, "rt");
|
||||||
if (pFile == nullptr) {
|
if (pFile == nullptr) {
|
||||||
printf("Cannot open file %s\n", path);
|
printf("Cannot open file %s\n", path);
|
||||||
return false;
|
return false;
|
||||||
@ -522,7 +524,7 @@ bool load_amf(const char *path, Model *model)
|
|||||||
|
|
||||||
bool store_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)
|
if (file == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <boost/nowide/convert.hpp>
|
||||||
|
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
#include <wx/wfstream.h>
|
#include <wx/wfstream.h>
|
||||||
#include <wx/zipstrm.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.
|
// To receive the content of the zipped 'scene.xml' file.
|
||||||
std::vector<char> scene_xml_data;
|
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);
|
wxZipInputStream zip(in);
|
||||||
std::unique_ptr<wxZipEntry> entry;
|
std::unique_ptr<wxZipEntry> entry;
|
||||||
size_t num_models = 0;
|
size_t num_models = 0;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <boost/nowide/cstdio.hpp>
|
||||||
|
|
||||||
#include "objparser.hpp"
|
#include "objparser.hpp"
|
||||||
|
|
||||||
namespace ObjParser {
|
namespace ObjParser {
|
||||||
@ -318,7 +320,7 @@ static bool obj_parseline(const char *line, ObjData &data)
|
|||||||
|
|
||||||
bool objparse(const char *path, ObjData &data)
|
bool objparse(const char *path, ObjData &data)
|
||||||
{
|
{
|
||||||
FILE *pFile = ::fopen(path, "rt");
|
FILE *pFile = boost::nowide::fopen(path, "rt");
|
||||||
if (pFile == 0)
|
if (pFile == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -446,7 +448,7 @@ bool loadvectornameidx(FILE *pFile, std::vector<T> &v)
|
|||||||
|
|
||||||
bool objbinsave(const char *path, const ObjData &data)
|
bool objbinsave(const char *path, const ObjData &data)
|
||||||
{
|
{
|
||||||
FILE *pFile = ::fopen(path, "wb");
|
FILE *pFile = boost::nowide::fopen(path, "wb");
|
||||||
if (pFile == 0)
|
if (pFile == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -471,7 +473,7 @@ bool objbinsave(const char *path, const ObjData &data)
|
|||||||
|
|
||||||
bool objbinload(const char *path, ObjData &data)
|
bool objbinload(const char *path, ObjData &data)
|
||||||
{
|
{
|
||||||
FILE *pFile = ::fopen(path, "rb");
|
FILE *pFile = boost::nowide::fopen(path, "rb");
|
||||||
if (pFile == 0)
|
if (pFile == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -13,6 +13,10 @@
|
|||||||
#include <boost/date_time/local_time/local_time.hpp>
|
#include <boost/date_time/local_time/local_time.hpp>
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
|
#include <boost/nowide/iostream.hpp>
|
||||||
|
#include <boost/nowide/cstdio.hpp>
|
||||||
|
#include <boost/nowide/cstdlib.hpp>
|
||||||
|
|
||||||
#include "SVG.hpp"
|
#include "SVG.hpp"
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -306,7 +310,33 @@ std::vector<std::pair<coordf_t, std::vector<GCode::LayerToPrint>>> GCode::collec
|
|||||||
return layers_to_print;
|
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?
|
// How many times will be change_layer() called?
|
||||||
// change_layer() in turn increments the progress bar status.
|
// change_layer() in turn increments the progress bar status.
|
||||||
|
@ -126,7 +126,7 @@ public:
|
|||||||
{}
|
{}
|
||||||
~GCode() {}
|
~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.
|
// Exported for the helper classes (OozePrevention, Wipe) and for the Perl binding for unit tests.
|
||||||
const Pointf& origin() const { return m_origin; }
|
const Pointf& origin() const { return m_origin; }
|
||||||
@ -146,6 +146,8 @@ public:
|
|||||||
void apply_print_config(const PrintConfig &print_config);
|
void apply_print_config(const PrintConfig &print_config);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool _do_export(Print &print, FILE *file);
|
||||||
|
|
||||||
// Object and support extrusions of the same PrintObject at the same print_z.
|
// Object and support extrusions of the same PrintObject at the same print_z.
|
||||||
struct LayerToPrint
|
struct LayerToPrint
|
||||||
{
|
{
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/nowide/iostream.hpp>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
@ -739,7 +740,7 @@ void ModelObject::print_info() const
|
|||||||
{
|
{
|
||||||
using namespace std;
|
using namespace std;
|
||||||
cout << fixed;
|
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();
|
TriangleMesh mesh = this->raw_mesh();
|
||||||
mesh.check_topology();
|
mesh.check_topology();
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "SVG.hpp"
|
#include "SVG.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <boost/nowide/cstdio.hpp>
|
||||||
|
|
||||||
#define COORD(x) ((float)unscale((x))*10)
|
#define COORD(x) ((float)unscale((x))*10)
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
@ -8,7 +10,7 @@ namespace Slic3r {
|
|||||||
bool SVG::open(const char* afilename)
|
bool SVG::open(const char* afilename)
|
||||||
{
|
{
|
||||||
this->filename = afilename;
|
this->filename = afilename;
|
||||||
this->f = fopen(afilename, "w");
|
this->f = boost::nowide::fopen(afilename, "w");
|
||||||
if (this->f == NULL)
|
if (this->f == NULL)
|
||||||
return false;
|
return false;
|
||||||
fprintf(this->f,
|
fprintf(this->f,
|
||||||
@ -27,7 +29,7 @@ bool SVG::open(const char* afilename, const BoundingBox &bbox, const coord_t bbo
|
|||||||
this->filename = afilename;
|
this->filename = afilename;
|
||||||
this->origin = bbox.min - Point(bbox_offset, bbox_offset);
|
this->origin = bbox.min - Point(bbox_offset, bbox_offset);
|
||||||
this->flipY = aflipY;
|
this->flipY = aflipY;
|
||||||
this->f = ::fopen(afilename, "w");
|
this->f = boost::nowide::fopen(afilename, "w");
|
||||||
if (f == NULL)
|
if (f == NULL)
|
||||||
return false;
|
return false;
|
||||||
float w = COORD(bbox.max.x - bbox.min.x + 2 * bbox_offset);
|
float w = COORD(bbox.max.x - bbox.min.x + 2 * bbox_offset);
|
||||||
|
@ -6,6 +6,10 @@ namespace Slic3r {
|
|||||||
extern void set_logging_level(unsigned int level);
|
extern void set_logging_level(unsigned int level);
|
||||||
extern void trace(unsigned int level, const char *message);
|
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
|
// Compute the next highest power of 2 of 32-bit v
|
||||||
// http://graphics.stanford.edu/~seander/bithacks.html
|
// http://graphics.stanford.edu/~seander/bithacks.html
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -1,7 +1,21 @@
|
|||||||
|
#include <locale>
|
||||||
|
|
||||||
#include <boost/log/core.hpp>
|
#include <boost/log/core.hpp>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
#include <boost/log/expressions.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 {
|
namespace Slic3r {
|
||||||
|
|
||||||
static boost::log::trivial::severity_level logSeverity = boost::log::trivial::error;
|
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.
|
// Force set_logging_level(<=error) after loading of the DLL.
|
||||||
static struct SetLoggingLevelOnInit {
|
// Switch boost::filesystem to utf8.
|
||||||
SetLoggingLevelOnInit() { set_logging_level(1); }
|
static struct RunOnInit {
|
||||||
} g_SetLoggingLevelOnInit;
|
RunOnInit() {
|
||||||
|
boost::nowide::nowide_filesystem();
|
||||||
|
set_logging_level(1);
|
||||||
|
}
|
||||||
|
} g_RunOnInit;
|
||||||
|
|
||||||
void trace(unsigned int level, const char *message)
|
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;
|
(::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
|
} // namespace Slic3r
|
||||||
|
|
||||||
#ifdef SLIC3R_HAS_BROKEN_CROAK
|
#ifdef SLIC3R_HAS_BROKEN_CROAK
|
||||||
|
@ -17,17 +17,7 @@
|
|||||||
%name{Slic3r::GCode} class GCode {
|
%name{Slic3r::GCode} class GCode {
|
||||||
GCode();
|
GCode();
|
||||||
~GCode();
|
~GCode();
|
||||||
std::string do_export(Print *print, const char *path)
|
std::string do_export(Print *print, const char *path);
|
||||||
%code{%
|
|
||||||
FILE *file = fopen(path, "wb");
|
|
||||||
if (file == nullptr) {
|
|
||||||
RETVAL = std::string("Failed to open ") + path + " for writing.";
|
|
||||||
} else {
|
|
||||||
THIS->do_export(file, *print);
|
|
||||||
fclose(file);
|
|
||||||
RETVAL = std::string();
|
|
||||||
}
|
|
||||||
%};
|
|
||||||
|
|
||||||
Ref<Pointf> origin()
|
Ref<Pointf> origin()
|
||||||
%code{% RETVAL = &(THIS->origin()); %};
|
%code{% RETVAL = &(THIS->origin()); %};
|
||||||
|
@ -48,6 +48,24 @@ trace(level, message)
|
|||||||
CODE:
|
CODE:
|
||||||
Slic3r::trace(level, message);
|
Slic3r::trace(level, message);
|
||||||
|
|
||||||
|
std::string
|
||||||
|
encode_path(src)
|
||||||
|
const char *src;
|
||||||
|
CODE:
|
||||||
|
Slic3r::encode_path(src);
|
||||||
|
|
||||||
|
std::string
|
||||||
|
decode_path(src)
|
||||||
|
const char *src;
|
||||||
|
CODE:
|
||||||
|
Slic3r::decode_path(src);
|
||||||
|
|
||||||
|
std::string
|
||||||
|
normalize_utf8_nfc(src)
|
||||||
|
const char *src;
|
||||||
|
CODE:
|
||||||
|
Slic3r::normalize_utf8_nfc(src);
|
||||||
|
|
||||||
void
|
void
|
||||||
xspp_test_croak_hangs_on_strawberry()
|
xspp_test_croak_hangs_on_strawberry()
|
||||||
CODE:
|
CODE:
|
||||||
|
Loading…
Reference in New Issue
Block a user