diff options
author | Alessandro Ranellucci <aar@cpan.org> | 2015-12-08 02:39:54 +0300 |
---|---|---|
committer | Alessandro Ranellucci <aar@cpan.org> | 2015-12-08 02:39:54 +0300 |
commit | 4913e90e100c093e81dd77f31e2cf39d844b9055 (patch) | |
tree | 2cbb9ded96107eb6db6d0ffdfd12b6ae33501976 /xs/src/perlglue.cpp | |
parent | 3fac8cd77e76da982219049629f3d9190cfcfbbf (diff) |
Remove any Perl related code from libslic3r
Diffstat (limited to 'xs/src/perlglue.cpp')
-rw-r--r-- | xs/src/perlglue.cpp | 537 |
1 files changed, 537 insertions, 0 deletions
diff --git a/xs/src/perlglue.cpp b/xs/src/perlglue.cpp new file mode 100644 index 000000000..22769e774 --- /dev/null +++ b/xs/src/perlglue.cpp @@ -0,0 +1,537 @@ +#ifdef SLIC3RXS +#include <xsinit.h> + +namespace Slic3r { + +REGISTER_CLASS(ExPolygon, "ExPolygon"); +REGISTER_CLASS(ExPolygonCollection, "ExPolygon::Collection"); +REGISTER_CLASS(Extruder, "Extruder"); +REGISTER_CLASS(ExtrusionPath, "ExtrusionPath"); +REGISTER_CLASS(ExtrusionLoop, "ExtrusionLoop"); +// there is no ExtrusionLoop::Collection or ExtrusionEntity::Collection +REGISTER_CLASS(ExtrusionEntityCollection, "ExtrusionPath::Collection"); +REGISTER_CLASS(Flow, "Flow"); +REGISTER_CLASS(AvoidCrossingPerimeters, "GCode::AvoidCrossingPerimeters"); +REGISTER_CLASS(OozePrevention, "GCode::OozePrevention"); +REGISTER_CLASS(Wipe, "GCode::Wipe"); +REGISTER_CLASS(GCode, "GCode"); +REGISTER_CLASS(GCodeSender, "GCode::Sender"); +REGISTER_CLASS(GCodeWriter, "GCode::Writer"); +REGISTER_CLASS(Layer, "Layer"); +REGISTER_CLASS(SupportLayer, "Layer::Support"); +REGISTER_CLASS(LayerRegion, "Layer::Region"); +REGISTER_CLASS(Line, "Line"); +REGISTER_CLASS(Linef3, "Linef3"); +REGISTER_CLASS(PerimeterGenerator, "Layer::PerimeterGenerator"); +REGISTER_CLASS(PlaceholderParser, "GCode::PlaceholderParser"); +REGISTER_CLASS(Polygon, "Polygon"); +REGISTER_CLASS(Polyline, "Polyline"); +REGISTER_CLASS(PolylineCollection, "Polyline::Collection"); +REGISTER_CLASS(Print, "Print"); +REGISTER_CLASS(PrintObject, "Print::Object"); +REGISTER_CLASS(PrintRegion, "Print::Region"); +REGISTER_CLASS(Model, "Model"); +REGISTER_CLASS(ModelMaterial, "Model::Material"); +REGISTER_CLASS(ModelObject, "Model::Object"); +REGISTER_CLASS(ModelVolume, "Model::Volume"); +REGISTER_CLASS(ModelInstance, "Model::Instance"); +REGISTER_CLASS(MotionPlanner, "MotionPlanner"); +REGISTER_CLASS(BoundingBox, "Geometry::BoundingBox"); +REGISTER_CLASS(BoundingBoxf, "Geometry::BoundingBoxf"); +REGISTER_CLASS(BoundingBoxf3, "Geometry::BoundingBoxf3"); +REGISTER_CLASS(BridgeDetector, "BridgeDetector"); +REGISTER_CLASS(Point, "Point"); +REGISTER_CLASS(Point3, "Point3"); +REGISTER_CLASS(Pointf, "Pointf"); +REGISTER_CLASS(Pointf3, "Pointf3"); +REGISTER_CLASS(DynamicPrintConfig, "Config"); +REGISTER_CLASS(PrintObjectConfig, "Config::PrintObject"); +REGISTER_CLASS(PrintRegionConfig, "Config::PrintRegion"); +REGISTER_CLASS(GCodeConfig, "Config::GCode"); +REGISTER_CLASS(PrintConfig, "Config::Print"); +REGISTER_CLASS(FullPrintConfig, "Config::Full"); +REGISTER_CLASS(Surface, "Surface"); +REGISTER_CLASS(SurfaceCollection, "Surface::Collection"); +REGISTER_CLASS(TriangleMesh, "TriangleMesh"); +REGISTER_CLASS(GLVertexArray, "GUI::_3DScene::GLVertexArray"); + +SV* +ConfigBase__as_hash(ConfigBase* THIS) { + HV* hv = newHV(); + + t_config_option_keys opt_keys = THIS->keys(); + for (t_config_option_keys::const_iterator it = opt_keys.begin(); it != opt_keys.end(); ++it) + (void)hv_store( hv, it->c_str(), it->length(), ConfigBase__get(THIS, *it), 0 ); + + return newRV_noinc((SV*)hv); +} + +SV* +ConfigBase__get(ConfigBase* THIS, const t_config_option_key &opt_key) { + ConfigOption* opt = THIS->option(opt_key); + if (opt == NULL) return &PL_sv_undef; + + const ConfigOptionDef* def = THIS->def->get(opt_key); + if (def->type == coFloat) { + ConfigOptionFloat* optv = dynamic_cast<ConfigOptionFloat*>(opt); + return newSVnv(optv->value); + } else if (def->type == coFloats) { + ConfigOptionFloats* optv = dynamic_cast<ConfigOptionFloats*>(opt); + AV* av = newAV(); + av_fill(av, optv->values.size()-1); + for (std::vector<double>::iterator it = optv->values.begin(); it != optv->values.end(); ++it) + av_store(av, it - optv->values.begin(), newSVnv(*it)); + return newRV_noinc((SV*)av); + } else if (def->type == coPercent) { + ConfigOptionPercent* optv = dynamic_cast<ConfigOptionPercent*>(opt); + return newSVnv(optv->value); + } else if (def->type == coInt) { + ConfigOptionInt* optv = dynamic_cast<ConfigOptionInt*>(opt); + return newSViv(optv->value); + } else if (def->type == coInts) { + ConfigOptionInts* optv = dynamic_cast<ConfigOptionInts*>(opt); + AV* av = newAV(); + av_fill(av, optv->values.size()-1); + for (std::vector<int>::iterator it = optv->values.begin(); it != optv->values.end(); ++it) + av_store(av, it - optv->values.begin(), newSViv(*it)); + return newRV_noinc((SV*)av); + } else if (def->type == coString) { + ConfigOptionString* optv = dynamic_cast<ConfigOptionString*>(opt); + // we don't serialize() because that would escape newlines + return newSVpvn_utf8(optv->value.c_str(), optv->value.length(), true); + } else if (def->type == coStrings) { + ConfigOptionStrings* optv = dynamic_cast<ConfigOptionStrings*>(opt); + AV* av = newAV(); + av_fill(av, optv->values.size()-1); + for (std::vector<std::string>::iterator it = optv->values.begin(); it != optv->values.end(); ++it) + av_store(av, it - optv->values.begin(), newSVpvn_utf8(it->c_str(), it->length(), true)); + return newRV_noinc((SV*)av); + } else if (def->type == coPoint) { + ConfigOptionPoint* optv = dynamic_cast<ConfigOptionPoint*>(opt); + return perl_to_SV_clone_ref(optv->value); + } else if (def->type == coPoints) { + ConfigOptionPoints* optv = dynamic_cast<ConfigOptionPoints*>(opt); + AV* av = newAV(); + av_fill(av, optv->values.size()-1); + for (Pointfs::iterator it = optv->values.begin(); it != optv->values.end(); ++it) + av_store(av, it - optv->values.begin(), perl_to_SV_clone_ref(*it)); + return newRV_noinc((SV*)av); + } else if (def->type == coBool) { + ConfigOptionBool* optv = dynamic_cast<ConfigOptionBool*>(opt); + return newSViv(optv->value ? 1 : 0); + } else if (def->type == coBools) { + ConfigOptionBools* optv = dynamic_cast<ConfigOptionBools*>(opt); + AV* av = newAV(); + av_fill(av, optv->values.size()-1); + for (std::vector<bool>::iterator it = optv->values.begin(); it != optv->values.end(); ++it) + av_store(av, it - optv->values.begin(), newSViv(*it ? 1 : 0)); + return newRV_noinc((SV*)av); + } else { + std::string serialized = opt->serialize(); + return newSVpvn_utf8(serialized.c_str(), serialized.length(), true); + } +} + +SV* +ConfigBase__get_at(ConfigBase* THIS, const t_config_option_key &opt_key, size_t i) { + ConfigOption* opt = THIS->option(opt_key); + if (opt == NULL) return &PL_sv_undef; + + const ConfigOptionDef* def = THIS->def->get(opt_key); + if (def->type == coFloats) { + ConfigOptionFloats* optv = dynamic_cast<ConfigOptionFloats*>(opt); + return newSVnv(optv->get_at(i)); + } else if (def->type == coInts) { + ConfigOptionInts* optv = dynamic_cast<ConfigOptionInts*>(opt); + return newSViv(optv->get_at(i)); + } else if (def->type == coStrings) { + ConfigOptionStrings* optv = dynamic_cast<ConfigOptionStrings*>(opt); + // we don't serialize() because that would escape newlines + std::string val = optv->get_at(i); + return newSVpvn_utf8(val.c_str(), val.length(), true); + } else if (def->type == coPoints) { + ConfigOptionPoints* optv = dynamic_cast<ConfigOptionPoints*>(opt); + return perl_to_SV_clone_ref(optv->get_at(i)); + } else if (def->type == coBools) { + ConfigOptionBools* optv = dynamic_cast<ConfigOptionBools*>(opt); + return newSViv(optv->get_at(i) ? 1 : 0); + } else { + return &PL_sv_undef; + } +} + +bool +ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value) { + ConfigOption* opt = THIS->option(opt_key, true); + if (opt == NULL) CONFESS("Trying to set non-existing option"); + + const ConfigOptionDef* def = THIS->def->get(opt_key); + if (def->type == coFloat) { + if (!looks_like_number(value)) return false; + ConfigOptionFloat* optv = dynamic_cast<ConfigOptionFloat*>(opt); + optv->value = SvNV(value); + } else if (def->type == coFloats) { + ConfigOptionFloats* optv = dynamic_cast<ConfigOptionFloats*>(opt); + std::vector<double> values; + AV* av = (AV*)SvRV(value); + const size_t len = av_len(av)+1; + for (size_t i = 0; i < len; i++) { + SV** elem = av_fetch(av, i, 0); + if (elem == NULL || !looks_like_number(*elem)) return false; + values.push_back(SvNV(*elem)); + } + optv->values = values; + } else if (def->type == coInt) { + if (!looks_like_number(value)) return false; + ConfigOptionInt* optv = dynamic_cast<ConfigOptionInt*>(opt); + optv->value = SvIV(value); + } else if (def->type == coInts) { + ConfigOptionInts* optv = dynamic_cast<ConfigOptionInts*>(opt); + std::vector<int> values; + AV* av = (AV*)SvRV(value); + const size_t len = av_len(av)+1; + for (size_t i = 0; i < len; i++) { + SV** elem = av_fetch(av, i, 0); + if (elem == NULL || !looks_like_number(*elem)) return false; + values.push_back(SvIV(*elem)); + } + optv->values = values; + } else if (def->type == coString) { + ConfigOptionString* optv = dynamic_cast<ConfigOptionString*>(opt); + optv->value = std::string(SvPV_nolen(value), SvCUR(value)); + } else if (def->type == coStrings) { + ConfigOptionStrings* optv = dynamic_cast<ConfigOptionStrings*>(opt); + optv->values.clear(); + AV* av = (AV*)SvRV(value); + const size_t len = av_len(av)+1; + for (size_t i = 0; i < len; i++) { + SV** elem = av_fetch(av, i, 0); + if (elem == NULL) return false; + optv->values.push_back(std::string(SvPV_nolen(*elem), SvCUR(*elem))); + } + } else if (def->type == coPoint) { + ConfigOptionPoint* optv = dynamic_cast<ConfigOptionPoint*>(opt); + return from_SV_check(value, &optv->value); + } else if (def->type == coPoints) { + ConfigOptionPoints* optv = dynamic_cast<ConfigOptionPoints*>(opt); + std::vector<Pointf> values; + AV* av = (AV*)SvRV(value); + const size_t len = av_len(av)+1; + for (size_t i = 0; i < len; i++) { + SV** elem = av_fetch(av, i, 0); + Pointf point; + if (elem == NULL || !from_SV_check(*elem, &point)) return false; + values.push_back(point); + } + optv->values = values; + } else if (def->type == coBool) { + ConfigOptionBool* optv = dynamic_cast<ConfigOptionBool*>(opt); + optv->value = SvTRUE(value); + } else if (def->type == coBools) { + ConfigOptionBools* optv = dynamic_cast<ConfigOptionBools*>(opt); + optv->values.clear(); + AV* av = (AV*)SvRV(value); + const size_t len = av_len(av)+1; + for (size_t i = 0; i < len; i++) { + SV** elem = av_fetch(av, i, 0); + if (elem == NULL) return false; + optv->values.push_back(SvTRUE(*elem)); + } + } else { + if (!opt->deserialize( std::string(SvPV_nolen(value)) )) return false; + } + return true; +} + +/* This method is implemented as a workaround for this typemap bug: + https://rt.cpan.org/Public/Bug/Display.html?id=94110 */ +bool +ConfigBase__set_deserialize(ConfigBase* THIS, const t_config_option_key &opt_key, SV* str) { + size_t len; + const char * c = SvPV(str, len); + std::string value(c, len); + + return THIS->set_deserialize(opt_key, value); +} + +void +ConfigBase__set_ifndef(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value, bool deserialize) +{ + if (!THIS->has(opt_key)) { + if (deserialize) { + ConfigBase__set_deserialize(THIS, opt_key, value); + } else { + ConfigBase__set(THIS, opt_key, value); + } + } +} + +bool +StaticConfig__set(StaticConfig* THIS, const t_config_option_key &opt_key, SV* value) { + const ConfigOptionDef* optdef = THIS->def->get(opt_key); + if (!optdef->shortcut.empty()) { + for (std::vector<t_config_option_key>::const_iterator it = optdef->shortcut.begin(); it != optdef->shortcut.end(); ++it) { + if (!StaticConfig__set(THIS, *it, value)) return false; + } + return true; + } + + return ConfigBase__set(THIS, opt_key, value); +} + +SV* to_AV(ExPolygon* expolygon) +{ + const unsigned int num_holes = expolygon->holes.size(); + AV* av = newAV(); + av_extend(av, num_holes); // -1 +1 + + av_store(av, 0, perl_to_SV_ref(expolygon->contour)); + + for (unsigned int i = 0; i < num_holes; i++) { + av_store(av, i+1, perl_to_SV_ref(expolygon->holes[i])); + } + return newRV_noinc((SV*)av); +} + +SV* to_SV_pureperl(const ExPolygon* expolygon) +{ + const unsigned int num_holes = expolygon->holes.size(); + AV* av = newAV(); + av_extend(av, num_holes); // -1 +1 + av_store(av, 0, to_SV_pureperl(&expolygon->contour)); + for (unsigned int i = 0; i < num_holes; i++) { + av_store(av, i+1, to_SV_pureperl(&expolygon->holes[i])); + } + return newRV_noinc((SV*)av); +} + +void from_SV(SV* expoly_sv, ExPolygon* expolygon) +{ + AV* expoly_av = (AV*)SvRV(expoly_sv); + const unsigned int num_polygons = av_len(expoly_av)+1; + expolygon->holes.resize(num_polygons-1); + + SV** polygon_sv = av_fetch(expoly_av, 0, 0); + from_SV(*polygon_sv, &expolygon->contour); + for (unsigned int i = 0; i < num_polygons-1; i++) { + polygon_sv = av_fetch(expoly_av, i+1, 0); + from_SV(*polygon_sv, &expolygon->holes[i]); + } +} + +void from_SV_check(SV* expoly_sv, ExPolygon* expolygon) +{ + if (sv_isobject(expoly_sv) && (SvTYPE(SvRV(expoly_sv)) == SVt_PVMG)) { + if (!sv_isa(expoly_sv, perl_class_name(expolygon)) && !sv_isa(expoly_sv, perl_class_name_ref(expolygon))) + CONFESS("Not a valid %s object", perl_class_name(expolygon)); + // a XS ExPolygon was supplied + *expolygon = *(ExPolygon *)SvIV((SV*)SvRV( expoly_sv )); + } else { + // a Perl arrayref was supplied + from_SV(expoly_sv, expolygon); + } +} + +void from_SV(SV* line_sv, Line* THIS) +{ + AV* line_av = (AV*)SvRV(line_sv); + from_SV_check(*av_fetch(line_av, 0, 0), &THIS->a); + from_SV_check(*av_fetch(line_av, 1, 0), &THIS->b); +} + +void from_SV_check(SV* line_sv, Line* THIS) +{ + if (sv_isobject(line_sv) && (SvTYPE(SvRV(line_sv)) == SVt_PVMG)) { + if (!sv_isa(line_sv, perl_class_name(THIS)) && !sv_isa(line_sv, perl_class_name_ref(THIS))) + CONFESS("Not a valid %s object", perl_class_name(THIS)); + *THIS = *(Line*)SvIV((SV*)SvRV( line_sv )); + } else { + from_SV(line_sv, THIS); + } +} + +SV* to_AV(Line* THIS) +{ + AV* av = newAV(); + av_extend(av, 1); + + av_store(av, 0, perl_to_SV_ref(THIS->a)); + av_store(av, 1, perl_to_SV_ref(THIS->b)); + + return newRV_noinc((SV*)av); +} + +SV* to_SV_pureperl(const Line* THIS) +{ + AV* av = newAV(); + av_extend(av, 1); + av_store(av, 0, to_SV_pureperl(&THIS->a)); + av_store(av, 1, to_SV_pureperl(&THIS->b)); + return newRV_noinc((SV*)av); +} + +void from_SV(SV* poly_sv, MultiPoint* THIS) +{ + AV* poly_av = (AV*)SvRV(poly_sv); + const unsigned int num_points = av_len(poly_av)+1; + THIS->points.resize(num_points); + + for (unsigned int i = 0; i < num_points; i++) { + SV** point_sv = av_fetch(poly_av, i, 0); + from_SV_check(*point_sv, &THIS->points[i]); + } +} + +void from_SV_check(SV* poly_sv, MultiPoint* THIS) +{ + if (sv_isobject(poly_sv) && (SvTYPE(SvRV(poly_sv)) == SVt_PVMG)) { + *THIS = *(MultiPoint*)SvIV((SV*)SvRV( poly_sv )); + } else { + from_SV(poly_sv, THIS); + } +} + +SV* to_AV(MultiPoint* THIS) +{ + const unsigned int num_points = THIS->points.size(); + AV* av = newAV(); + if (num_points > 0) av_extend(av, num_points-1); + for (unsigned int i = 0; i < num_points; i++) { + av_store(av, i, perl_to_SV_ref(THIS->points[i])); + } + return newRV_noinc((SV*)av); +} + +SV* to_SV_pureperl(const MultiPoint* THIS) +{ + const unsigned int num_points = THIS->points.size(); + AV* av = newAV(); + if (num_points > 0) av_extend(av, num_points-1); + for (unsigned int i = 0; i < num_points; i++) { + av_store(av, i, to_SV_pureperl(&THIS->points[i])); + } + return newRV_noinc((SV*)av); +} + +void from_SV_check(SV* poly_sv, Polygon* THIS) +{ + if (sv_isobject(poly_sv) && !sv_isa(poly_sv, perl_class_name(THIS)) && !sv_isa(poly_sv, perl_class_name_ref(THIS))) + CONFESS("Not a valid %s object", perl_class_name(THIS)); + + from_SV_check(poly_sv, (MultiPoint*)THIS); +} + +void from_SV_check(SV* poly_sv, Polyline* THIS) +{ + if (!sv_isa(poly_sv, perl_class_name(THIS)) && !sv_isa(poly_sv, perl_class_name_ref(THIS))) + CONFESS("Not a valid %s object", perl_class_name(THIS)); + + from_SV_check(poly_sv, (MultiPoint*)THIS); +} + +SV* to_SV_pureperl(const Point* THIS) +{ + AV* av = newAV(); + av_fill(av, 1); + av_store(av, 0, newSViv(THIS->x)); + av_store(av, 1, newSViv(THIS->y)); + return newRV_noinc((SV*)av); +} + +void from_SV(SV* point_sv, Point* point) +{ + AV* point_av = (AV*)SvRV(point_sv); + // get a double from Perl and round it, otherwise + // it would get truncated + point->x = lrint(SvNV(*av_fetch(point_av, 0, 0))); + point->y = lrint(SvNV(*av_fetch(point_av, 1, 0))); +} + +void from_SV_check(SV* point_sv, Point* point) +{ + if (sv_isobject(point_sv) && (SvTYPE(SvRV(point_sv)) == SVt_PVMG)) { + if (!sv_isa(point_sv, perl_class_name(point)) && !sv_isa(point_sv, perl_class_name_ref(point))) + CONFESS("Not a valid %s object (got %s)", perl_class_name(point), HvNAME(SvSTASH(SvRV(point_sv)))); + *point = *(Point*)SvIV((SV*)SvRV( point_sv )); + } else { + from_SV(point_sv, point); + } +} + +SV* to_SV_pureperl(const Pointf* point) +{ + AV* av = newAV(); + av_fill(av, 1); + av_store(av, 0, newSVnv(point->x)); + av_store(av, 1, newSVnv(point->y)); + return newRV_noinc((SV*)av); +} + +bool from_SV(SV* point_sv, Pointf* point) +{ + AV* point_av = (AV*)SvRV(point_sv); + SV* sv_x = *av_fetch(point_av, 0, 0); + SV* sv_y = *av_fetch(point_av, 1, 0); + if (!looks_like_number(sv_x) || !looks_like_number(sv_y)) return false; + + point->x = SvNV(sv_x); + point->y = SvNV(sv_y); + return true; +} + +bool from_SV_check(SV* point_sv, Pointf* point) +{ + if (sv_isobject(point_sv) && (SvTYPE(SvRV(point_sv)) == SVt_PVMG)) { + if (!sv_isa(point_sv, perl_class_name(point)) && !sv_isa(point_sv, perl_class_name_ref(point))) + CONFESS("Not a valid %s object (got %s)", perl_class_name(point), HvNAME(SvSTASH(SvRV(point_sv)))); + *point = *(Pointf*)SvIV((SV*)SvRV( point_sv )); + return true; + } else { + return from_SV(point_sv, point); + } +} + +void from_SV_check(SV* surface_sv, Surface* THIS) +{ + if (!sv_isa(surface_sv, perl_class_name(THIS)) && !sv_isa(surface_sv, perl_class_name_ref(THIS))) + CONFESS("Not a valid %s object", perl_class_name(THIS)); + // a XS Surface was supplied + *THIS = *(Surface *)SvIV((SV*)SvRV( surface_sv )); +} + +SV* to_SV(TriangleMesh* THIS) +{ + SV* sv = newSV(0); + sv_setref_pv( sv, perl_class_name(THIS), (void*)THIS ); + return sv; +} + +SV* +polynode_children_2_perl(const ClipperLib::PolyNode& node) +{ + AV* av = newAV(); + const int len = node.ChildCount(); + if (len > 0) av_extend(av, len-1); + for (int i = 0; i < len; ++i) { + av_store(av, i, polynode2perl(*node.Childs[i])); + } + return (SV*)newRV_noinc((SV*)av); +} + +SV* +polynode2perl(const ClipperLib::PolyNode& node) +{ + HV* hv = newHV(); + Slic3r::Polygon p; + ClipperPath_to_Slic3rMultiPoint(node.Contour, &p); + if (node.IsHole()) { + (void)hv_stores( hv, "hole", Slic3r::perl_to_SV_clone_ref(p) ); + } else { + (void)hv_stores( hv, "outer", Slic3r::perl_to_SV_clone_ref(p) ); + } + (void)hv_stores( hv, "children", polynode_children_2_perl(node) ); + return (SV*)newRV_noinc((SV*)hv); +} + +} +#endif |