perlglue.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. #ifdef SLIC3RXS
  2. #include <xsinit.h>
  3. namespace Slic3r {
  4. REGISTER_CLASS(ExPolygon, "ExPolygon");
  5. REGISTER_CLASS(ExPolygonCollection, "ExPolygon::Collection");
  6. REGISTER_CLASS(ExtrusionMultiPath, "ExtrusionMultiPath");
  7. REGISTER_CLASS(ExtrusionPath, "ExtrusionPath");
  8. REGISTER_CLASS(ExtrusionLoop, "ExtrusionLoop");
  9. // there is no ExtrusionLoop::Collection or ExtrusionEntity::Collection
  10. REGISTER_CLASS(ExtrusionEntityCollection, "ExtrusionPath::Collection");
  11. REGISTER_CLASS(ExtrusionSimulator, "ExtrusionSimulator");
  12. REGISTER_CLASS(Filler, "Filler");
  13. REGISTER_CLASS(Flow, "Flow");
  14. REGISTER_CLASS(CoolingBuffer, "GCode::CoolingBuffer");
  15. REGISTER_CLASS(GCode, "GCode");
  16. REGISTER_CLASS(GCodeSender, "GCode::Sender");
  17. REGISTER_CLASS(Layer, "Layer");
  18. REGISTER_CLASS(SupportLayer, "Layer::Support");
  19. REGISTER_CLASS(LayerRegion, "Layer::Region");
  20. REGISTER_CLASS(Line, "Line");
  21. REGISTER_CLASS(Linef3, "Linef3");
  22. REGISTER_CLASS(PerimeterGenerator, "Layer::PerimeterGenerator");
  23. REGISTER_CLASS(PlaceholderParser, "GCode::PlaceholderParser");
  24. REGISTER_CLASS(Polygon, "Polygon");
  25. REGISTER_CLASS(Polyline, "Polyline");
  26. REGISTER_CLASS(PolylineCollection, "Polyline::Collection");
  27. REGISTER_CLASS(Print, "Print");
  28. REGISTER_CLASS(PrintObject, "Print::Object");
  29. REGISTER_CLASS(PrintRegion, "Print::Region");
  30. REGISTER_CLASS(Model, "Model");
  31. REGISTER_CLASS(ModelMaterial, "Model::Material");
  32. REGISTER_CLASS(ModelObject, "Model::Object");
  33. REGISTER_CLASS(ModelVolume, "Model::Volume");
  34. REGISTER_CLASS(ModelInstance, "Model::Instance");
  35. REGISTER_CLASS(MotionPlanner, "MotionPlanner");
  36. REGISTER_CLASS(BoundingBox, "Geometry::BoundingBox");
  37. REGISTER_CLASS(BoundingBoxf, "Geometry::BoundingBoxf");
  38. REGISTER_CLASS(BoundingBoxf3, "Geometry::BoundingBoxf3");
  39. REGISTER_CLASS(BridgeDetector, "BridgeDetector");
  40. REGISTER_CLASS(Point, "Point");
  41. REGISTER_CLASS(Point3, "Point3");
  42. REGISTER_CLASS(Pointf, "Pointf");
  43. REGISTER_CLASS(Pointf3, "Pointf3");
  44. REGISTER_CLASS(DynamicPrintConfig, "Config");
  45. REGISTER_CLASS(StaticPrintConfig, "Config::Static");
  46. REGISTER_CLASS(PrintObjectConfig, "Config::PrintObject");
  47. REGISTER_CLASS(PrintRegionConfig, "Config::PrintRegion");
  48. REGISTER_CLASS(GCodeConfig, "Config::GCode");
  49. REGISTER_CLASS(PrintConfig, "Config::Print");
  50. REGISTER_CLASS(FullPrintConfig, "Config::Full");
  51. REGISTER_CLASS(Surface, "Surface");
  52. REGISTER_CLASS(SurfaceCollection, "Surface::Collection");
  53. REGISTER_CLASS(PrintObjectSupportMaterial, "Print::SupportMaterial2");
  54. REGISTER_CLASS(TriangleMesh, "TriangleMesh");
  55. REGISTER_CLASS(GLShader, "GUI::_3DScene::GLShader");
  56. REGISTER_CLASS(GLVolume, "GUI::_3DScene::GLVolume");
  57. REGISTER_CLASS(GLVolumeCollection, "GUI::_3DScene::GLVolume::Collection");
  58. SV*
  59. ConfigBase__as_hash(ConfigBase* THIS) {
  60. HV* hv = newHV();
  61. t_config_option_keys opt_keys = THIS->keys();
  62. for (t_config_option_keys::const_iterator it = opt_keys.begin(); it != opt_keys.end(); ++it)
  63. (void)hv_store( hv, it->c_str(), it->length(), ConfigBase__get(THIS, *it), 0 );
  64. return newRV_noinc((SV*)hv);
  65. }
  66. SV*
  67. ConfigBase__get(ConfigBase* THIS, const t_config_option_key &opt_key) {
  68. ConfigOption* opt = THIS->option(opt_key);
  69. if (opt == NULL) return &PL_sv_undef;
  70. const ConfigOptionDef* def = THIS->def->get(opt_key);
  71. return ConfigOption_to_SV(*opt, *def);
  72. }
  73. SV*
  74. ConfigOption_to_SV(const ConfigOption &opt, const ConfigOptionDef &def) {
  75. if (def.type == coFloat) {
  76. const ConfigOptionFloat* optv = dynamic_cast<const ConfigOptionFloat*>(&opt);
  77. return newSVnv(optv->value);
  78. } else if (def.type == coFloats) {
  79. const ConfigOptionFloats* optv = dynamic_cast<const ConfigOptionFloats*>(&opt);
  80. AV* av = newAV();
  81. av_fill(av, optv->values.size()-1);
  82. for (std::vector<double>::const_iterator it = optv->values.begin(); it != optv->values.end(); ++it)
  83. av_store(av, it - optv->values.begin(), newSVnv(*it));
  84. return newRV_noinc((SV*)av);
  85. } else if (def.type == coPercent) {
  86. const ConfigOptionPercent* optv = dynamic_cast<const ConfigOptionPercent*>(&opt);
  87. return newSVnv(optv->value);
  88. } else if (def.type == coPercents) {
  89. const ConfigOptionPercents* optv = dynamic_cast<const ConfigOptionPercents*>(&opt);
  90. AV* av = newAV();
  91. av_fill(av, optv->values.size()-1);
  92. for (const double &v : optv->values)
  93. av_store(av, &v - &optv->values.front(), newSVnv(v));
  94. return newRV_noinc((SV*)av);
  95. } else if (def.type == coInt) {
  96. const ConfigOptionInt* optv = dynamic_cast<const ConfigOptionInt*>(&opt);
  97. return newSViv(optv->value);
  98. } else if (def.type == coInts) {
  99. const ConfigOptionInts* optv = dynamic_cast<const ConfigOptionInts*>(&opt);
  100. AV* av = newAV();
  101. av_fill(av, optv->values.size()-1);
  102. for (std::vector<int>::const_iterator it = optv->values.begin(); it != optv->values.end(); ++it)
  103. av_store(av, it - optv->values.begin(), newSViv(*it));
  104. return newRV_noinc((SV*)av);
  105. } else if (def.type == coString) {
  106. const ConfigOptionString* optv = dynamic_cast<const ConfigOptionString*>(&opt);
  107. // we don't serialize() because that would escape newlines
  108. return newSVpvn_utf8(optv->value.c_str(), optv->value.length(), true);
  109. } else if (def.type == coStrings) {
  110. const ConfigOptionStrings* optv = dynamic_cast<const ConfigOptionStrings*>(&opt);
  111. AV* av = newAV();
  112. av_fill(av, optv->values.size()-1);
  113. for (std::vector<std::string>::const_iterator it = optv->values.begin(); it != optv->values.end(); ++it)
  114. av_store(av, it - optv->values.begin(), newSVpvn_utf8(it->c_str(), it->length(), true));
  115. return newRV_noinc((SV*)av);
  116. } else if (def.type == coPoint) {
  117. const ConfigOptionPoint* optv = dynamic_cast<const ConfigOptionPoint*>(&opt);
  118. return perl_to_SV_clone_ref(optv->value);
  119. } else if (def.type == coPoints) {
  120. const ConfigOptionPoints* optv = dynamic_cast<const ConfigOptionPoints*>(&opt);
  121. AV* av = newAV();
  122. av_fill(av, optv->values.size()-1);
  123. for (Pointfs::const_iterator it = optv->values.begin(); it != optv->values.end(); ++it)
  124. av_store(av, it - optv->values.begin(), perl_to_SV_clone_ref(*it));
  125. return newRV_noinc((SV*)av);
  126. } else if (def.type == coBool) {
  127. const ConfigOptionBool* optv = dynamic_cast<const ConfigOptionBool*>(&opt);
  128. return newSViv(optv->value ? 1 : 0);
  129. } else if (def.type == coBools) {
  130. const ConfigOptionBools* optv = dynamic_cast<const ConfigOptionBools*>(&opt);
  131. AV* av = newAV();
  132. av_fill(av, optv->values.size()-1);
  133. for (std::vector<bool>::const_iterator it = optv->values.begin(); it != optv->values.end(); ++it)
  134. av_store(av, it - optv->values.begin(), newSViv(*it ? 1 : 0));
  135. return newRV_noinc((SV*)av);
  136. } else {
  137. std::string serialized = opt.serialize();
  138. return newSVpvn_utf8(serialized.c_str(), serialized.length(), true);
  139. }
  140. }
  141. SV*
  142. ConfigBase__get_at(ConfigBase* THIS, const t_config_option_key &opt_key, size_t i) {
  143. ConfigOption* opt = THIS->option(opt_key);
  144. if (opt == NULL) return &PL_sv_undef;
  145. const ConfigOptionDef* def = THIS->def->get(opt_key);
  146. if (def->type == coFloats || def->type == coPercents) {
  147. ConfigOptionFloats* optv = dynamic_cast<ConfigOptionFloats*>(opt);
  148. return newSVnv(optv->get_at(i));
  149. } else if (def->type == coInts) {
  150. ConfigOptionInts* optv = dynamic_cast<ConfigOptionInts*>(opt);
  151. return newSViv(optv->get_at(i));
  152. } else if (def->type == coStrings) {
  153. ConfigOptionStrings* optv = dynamic_cast<ConfigOptionStrings*>(opt);
  154. // we don't serialize() because that would escape newlines
  155. std::string val = optv->get_at(i);
  156. return newSVpvn_utf8(val.c_str(), val.length(), true);
  157. } else if (def->type == coPoints) {
  158. ConfigOptionPoints* optv = dynamic_cast<ConfigOptionPoints*>(opt);
  159. return perl_to_SV_clone_ref(optv->get_at(i));
  160. } else if (def->type == coBools) {
  161. ConfigOptionBools* optv = dynamic_cast<ConfigOptionBools*>(opt);
  162. return newSViv(optv->get_at(i) ? 1 : 0);
  163. } else {
  164. return &PL_sv_undef;
  165. }
  166. }
  167. bool
  168. ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value) {
  169. ConfigOption* opt = THIS->option(opt_key, true);
  170. if (opt == NULL) CONFESS("Trying to set non-existing option");
  171. const ConfigOptionDef* def = THIS->def->get(opt_key);
  172. if (def->type == coFloat) {
  173. if (!looks_like_number(value)) return false;
  174. ConfigOptionFloat* optv = dynamic_cast<ConfigOptionFloat*>(opt);
  175. optv->value = SvNV(value);
  176. } else if (def->type == coFloats) {
  177. ConfigOptionFloats* optv = dynamic_cast<ConfigOptionFloats*>(opt);
  178. std::vector<double> values;
  179. AV* av = (AV*)SvRV(value);
  180. const size_t len = av_len(av)+1;
  181. for (size_t i = 0; i < len; i++) {
  182. SV** elem = av_fetch(av, i, 0);
  183. if (elem == NULL || !looks_like_number(*elem)) return false;
  184. values.push_back(SvNV(*elem));
  185. }
  186. optv->values = values;
  187. } else if (def->type == coPercents) {
  188. ConfigOptionPercents* optv = dynamic_cast<ConfigOptionPercents*>(opt);
  189. std::vector<double> values;
  190. AV* av = (AV*)SvRV(value);
  191. const size_t len = av_len(av)+1;
  192. for (size_t i = 0; i < len; i++) {
  193. SV** elem = av_fetch(av, i, 0);
  194. if (elem == NULL || !looks_like_number(*elem)) return false;
  195. values.push_back(SvNV(*elem));
  196. }
  197. optv->values = values;
  198. } else if (def->type == coInt) {
  199. if (!looks_like_number(value)) return false;
  200. ConfigOptionInt* optv = dynamic_cast<ConfigOptionInt*>(opt);
  201. optv->value = SvIV(value);
  202. } else if (def->type == coInts) {
  203. ConfigOptionInts* optv = dynamic_cast<ConfigOptionInts*>(opt);
  204. std::vector<int> values;
  205. AV* av = (AV*)SvRV(value);
  206. const size_t len = av_len(av)+1;
  207. for (size_t i = 0; i < len; i++) {
  208. SV** elem = av_fetch(av, i, 0);
  209. if (elem == NULL || !looks_like_number(*elem)) return false;
  210. values.push_back(SvIV(*elem));
  211. }
  212. optv->values = values;
  213. } else if (def->type == coString) {
  214. ConfigOptionString* optv = dynamic_cast<ConfigOptionString*>(opt);
  215. optv->value = std::string(SvPV_nolen(value), SvCUR(value));
  216. } else if (def->type == coStrings) {
  217. ConfigOptionStrings* optv = dynamic_cast<ConfigOptionStrings*>(opt);
  218. optv->values.clear();
  219. AV* av = (AV*)SvRV(value);
  220. const size_t len = av_len(av)+1;
  221. for (size_t i = 0; i < len; i++) {
  222. SV** elem = av_fetch(av, i, 0);
  223. if (elem == NULL) return false;
  224. optv->values.push_back(std::string(SvPV_nolen(*elem), SvCUR(*elem)));
  225. }
  226. } else if (def->type == coPoint) {
  227. ConfigOptionPoint* optv = dynamic_cast<ConfigOptionPoint*>(opt);
  228. return from_SV_check(value, &optv->value);
  229. } else if (def->type == coPoints) {
  230. ConfigOptionPoints* optv = dynamic_cast<ConfigOptionPoints*>(opt);
  231. std::vector<Pointf> values;
  232. AV* av = (AV*)SvRV(value);
  233. const size_t len = av_len(av)+1;
  234. for (size_t i = 0; i < len; i++) {
  235. SV** elem = av_fetch(av, i, 0);
  236. Pointf point;
  237. if (elem == NULL || !from_SV_check(*elem, &point)) return false;
  238. values.push_back(point);
  239. }
  240. optv->values = values;
  241. } else if (def->type == coBool) {
  242. ConfigOptionBool* optv = dynamic_cast<ConfigOptionBool*>(opt);
  243. optv->value = SvTRUE(value);
  244. } else if (def->type == coBools) {
  245. ConfigOptionBools* optv = dynamic_cast<ConfigOptionBools*>(opt);
  246. optv->values.clear();
  247. AV* av = (AV*)SvRV(value);
  248. const size_t len = av_len(av)+1;
  249. for (size_t i = 0; i < len; i++) {
  250. SV** elem = av_fetch(av, i, 0);
  251. if (elem == NULL) return false;
  252. optv->values.push_back(SvTRUE(*elem));
  253. }
  254. } else {
  255. if (!opt->deserialize( std::string(SvPV_nolen(value)) )) return false;
  256. }
  257. return true;
  258. }
  259. /* This method is implemented as a workaround for this typemap bug:
  260. https://rt.cpan.org/Public/Bug/Display.html?id=94110 */
  261. bool
  262. ConfigBase__set_deserialize(ConfigBase* THIS, const t_config_option_key &opt_key, SV* str) {
  263. size_t len;
  264. const char * c = SvPV(str, len);
  265. std::string value(c, len);
  266. return THIS->set_deserialize(opt_key, value);
  267. }
  268. void
  269. ConfigBase__set_ifndef(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value, bool deserialize)
  270. {
  271. if (!THIS->has(opt_key)) {
  272. if (deserialize) {
  273. ConfigBase__set_deserialize(THIS, opt_key, value);
  274. } else {
  275. ConfigBase__set(THIS, opt_key, value);
  276. }
  277. }
  278. }
  279. bool
  280. StaticConfig__set(StaticConfig* THIS, const t_config_option_key &opt_key, SV* value) {
  281. const ConfigOptionDef* optdef = THIS->def->get(opt_key);
  282. if (!optdef->shortcut.empty()) {
  283. for (std::vector<t_config_option_key>::const_iterator it = optdef->shortcut.begin(); it != optdef->shortcut.end(); ++it) {
  284. if (!StaticConfig__set(THIS, *it, value)) return false;
  285. }
  286. return true;
  287. }
  288. return ConfigBase__set(THIS, opt_key, value);
  289. }
  290. SV* to_AV(ExPolygon* expolygon)
  291. {
  292. const unsigned int num_holes = expolygon->holes.size();
  293. AV* av = newAV();
  294. av_extend(av, num_holes); // -1 +1
  295. av_store(av, 0, perl_to_SV_ref(expolygon->contour));
  296. for (unsigned int i = 0; i < num_holes; i++) {
  297. av_store(av, i+1, perl_to_SV_ref(expolygon->holes[i]));
  298. }
  299. return newRV_noinc((SV*)av);
  300. }
  301. SV* to_SV_pureperl(const ExPolygon* expolygon)
  302. {
  303. const unsigned int num_holes = expolygon->holes.size();
  304. AV* av = newAV();
  305. av_extend(av, num_holes); // -1 +1
  306. av_store(av, 0, to_SV_pureperl(&expolygon->contour));
  307. for (unsigned int i = 0; i < num_holes; i++) {
  308. av_store(av, i+1, to_SV_pureperl(&expolygon->holes[i]));
  309. }
  310. return newRV_noinc((SV*)av);
  311. }
  312. void from_SV(SV* expoly_sv, ExPolygon* expolygon)
  313. {
  314. AV* expoly_av = (AV*)SvRV(expoly_sv);
  315. const unsigned int num_polygons = av_len(expoly_av)+1;
  316. expolygon->holes.resize(num_polygons-1);
  317. SV** polygon_sv = av_fetch(expoly_av, 0, 0);
  318. from_SV(*polygon_sv, &expolygon->contour);
  319. for (unsigned int i = 0; i < num_polygons-1; i++) {
  320. polygon_sv = av_fetch(expoly_av, i+1, 0);
  321. from_SV(*polygon_sv, &expolygon->holes[i]);
  322. }
  323. }
  324. void from_SV_check(SV* expoly_sv, ExPolygon* expolygon)
  325. {
  326. if (sv_isobject(expoly_sv) && (SvTYPE(SvRV(expoly_sv)) == SVt_PVMG)) {
  327. if (!sv_isa(expoly_sv, perl_class_name(expolygon)) && !sv_isa(expoly_sv, perl_class_name_ref(expolygon)))
  328. CONFESS("Not a valid %s object", perl_class_name(expolygon));
  329. // a XS ExPolygon was supplied
  330. *expolygon = *(ExPolygon *)SvIV((SV*)SvRV( expoly_sv ));
  331. } else {
  332. // a Perl arrayref was supplied
  333. from_SV(expoly_sv, expolygon);
  334. }
  335. }
  336. void from_SV(SV* line_sv, Line* THIS)
  337. {
  338. AV* line_av = (AV*)SvRV(line_sv);
  339. from_SV_check(*av_fetch(line_av, 0, 0), &THIS->a);
  340. from_SV_check(*av_fetch(line_av, 1, 0), &THIS->b);
  341. }
  342. void from_SV_check(SV* line_sv, Line* THIS)
  343. {
  344. if (sv_isobject(line_sv) && (SvTYPE(SvRV(line_sv)) == SVt_PVMG)) {
  345. if (!sv_isa(line_sv, perl_class_name(THIS)) && !sv_isa(line_sv, perl_class_name_ref(THIS)))
  346. CONFESS("Not a valid %s object", perl_class_name(THIS));
  347. *THIS = *(Line*)SvIV((SV*)SvRV( line_sv ));
  348. } else {
  349. from_SV(line_sv, THIS);
  350. }
  351. }
  352. SV* to_AV(Line* THIS)
  353. {
  354. AV* av = newAV();
  355. av_extend(av, 1);
  356. av_store(av, 0, perl_to_SV_ref(THIS->a));
  357. av_store(av, 1, perl_to_SV_ref(THIS->b));
  358. return newRV_noinc((SV*)av);
  359. }
  360. SV* to_SV_pureperl(const Line* THIS)
  361. {
  362. AV* av = newAV();
  363. av_extend(av, 1);
  364. av_store(av, 0, to_SV_pureperl(&THIS->a));
  365. av_store(av, 1, to_SV_pureperl(&THIS->b));
  366. return newRV_noinc((SV*)av);
  367. }
  368. void from_SV(SV* poly_sv, MultiPoint* THIS)
  369. {
  370. AV* poly_av = (AV*)SvRV(poly_sv);
  371. const unsigned int num_points = av_len(poly_av)+1;
  372. THIS->points.resize(num_points);
  373. for (unsigned int i = 0; i < num_points; i++) {
  374. SV** point_sv = av_fetch(poly_av, i, 0);
  375. from_SV_check(*point_sv, &THIS->points[i]);
  376. }
  377. }
  378. void from_SV_check(SV* poly_sv, MultiPoint* THIS)
  379. {
  380. if (sv_isobject(poly_sv) && (SvTYPE(SvRV(poly_sv)) == SVt_PVMG)) {
  381. *THIS = *(MultiPoint*)SvIV((SV*)SvRV( poly_sv ));
  382. } else {
  383. from_SV(poly_sv, THIS);
  384. }
  385. }
  386. SV* to_AV(MultiPoint* THIS)
  387. {
  388. const unsigned int num_points = THIS->points.size();
  389. AV* av = newAV();
  390. if (num_points > 0) av_extend(av, num_points-1);
  391. for (unsigned int i = 0; i < num_points; i++) {
  392. av_store(av, i, perl_to_SV_ref(THIS->points[i]));
  393. }
  394. return newRV_noinc((SV*)av);
  395. }
  396. SV* to_SV_pureperl(const MultiPoint* THIS)
  397. {
  398. const unsigned int num_points = THIS->points.size();
  399. AV* av = newAV();
  400. if (num_points > 0) av_extend(av, num_points-1);
  401. for (unsigned int i = 0; i < num_points; i++) {
  402. av_store(av, i, to_SV_pureperl(&THIS->points[i]));
  403. }
  404. return newRV_noinc((SV*)av);
  405. }
  406. void from_SV_check(SV* poly_sv, Polygon* THIS)
  407. {
  408. if (sv_isobject(poly_sv) && !sv_isa(poly_sv, perl_class_name(THIS)) && !sv_isa(poly_sv, perl_class_name_ref(THIS)))
  409. CONFESS("Not a valid %s object", perl_class_name(THIS));
  410. from_SV_check(poly_sv, (MultiPoint*)THIS);
  411. }
  412. void from_SV_check(SV* poly_sv, Polyline* THIS)
  413. {
  414. if (!sv_isa(poly_sv, perl_class_name(THIS)) && !sv_isa(poly_sv, perl_class_name_ref(THIS)))
  415. CONFESS("Not a valid %s object", perl_class_name(THIS));
  416. from_SV_check(poly_sv, (MultiPoint*)THIS);
  417. }
  418. SV* to_SV_pureperl(const Point* THIS)
  419. {
  420. AV* av = newAV();
  421. av_fill(av, 1);
  422. av_store(av, 0, newSViv(THIS->x));
  423. av_store(av, 1, newSViv(THIS->y));
  424. return newRV_noinc((SV*)av);
  425. }
  426. void from_SV(SV* point_sv, Point* point)
  427. {
  428. AV* point_av = (AV*)SvRV(point_sv);
  429. // get a double from Perl and round it, otherwise
  430. // it would get truncated
  431. point->x = lrint(SvNV(*av_fetch(point_av, 0, 0)));
  432. point->y = lrint(SvNV(*av_fetch(point_av, 1, 0)));
  433. }
  434. void from_SV_check(SV* point_sv, Point* point)
  435. {
  436. if (sv_isobject(point_sv) && (SvTYPE(SvRV(point_sv)) == SVt_PVMG)) {
  437. if (!sv_isa(point_sv, perl_class_name(point)) && !sv_isa(point_sv, perl_class_name_ref(point)))
  438. CONFESS("Not a valid %s object (got %s)", perl_class_name(point), HvNAME(SvSTASH(SvRV(point_sv))));
  439. *point = *(Point*)SvIV((SV*)SvRV( point_sv ));
  440. } else {
  441. from_SV(point_sv, point);
  442. }
  443. }
  444. SV* to_SV_pureperl(const Pointf* point)
  445. {
  446. AV* av = newAV();
  447. av_fill(av, 1);
  448. av_store(av, 0, newSVnv(point->x));
  449. av_store(av, 1, newSVnv(point->y));
  450. return newRV_noinc((SV*)av);
  451. }
  452. bool from_SV(SV* point_sv, Pointf* point)
  453. {
  454. AV* point_av = (AV*)SvRV(point_sv);
  455. SV* sv_x = *av_fetch(point_av, 0, 0);
  456. SV* sv_y = *av_fetch(point_av, 1, 0);
  457. if (!looks_like_number(sv_x) || !looks_like_number(sv_y)) return false;
  458. point->x = SvNV(sv_x);
  459. point->y = SvNV(sv_y);
  460. return true;
  461. }
  462. bool from_SV_check(SV* point_sv, Pointf* point)
  463. {
  464. if (sv_isobject(point_sv) && (SvTYPE(SvRV(point_sv)) == SVt_PVMG)) {
  465. if (!sv_isa(point_sv, perl_class_name(point)) && !sv_isa(point_sv, perl_class_name_ref(point)))
  466. CONFESS("Not a valid %s object (got %s)", perl_class_name(point), HvNAME(SvSTASH(SvRV(point_sv))));
  467. *point = *(Pointf*)SvIV((SV*)SvRV( point_sv ));
  468. return true;
  469. } else {
  470. return from_SV(point_sv, point);
  471. }
  472. }
  473. void from_SV_check(SV* surface_sv, Surface* THIS)
  474. {
  475. if (!sv_isa(surface_sv, perl_class_name(THIS)) && !sv_isa(surface_sv, perl_class_name_ref(THIS)))
  476. CONFESS("Not a valid %s object", perl_class_name(THIS));
  477. // a XS Surface was supplied
  478. *THIS = *(Surface *)SvIV((SV*)SvRV( surface_sv ));
  479. }
  480. SV* to_SV(TriangleMesh* THIS)
  481. {
  482. SV* sv = newSV(0);
  483. sv_setref_pv( sv, perl_class_name(THIS), (void*)THIS );
  484. return sv;
  485. }
  486. SV*
  487. polynode_children_2_perl(const ClipperLib::PolyNode& node)
  488. {
  489. AV* av = newAV();
  490. const int len = node.ChildCount();
  491. if (len > 0) av_extend(av, len-1);
  492. for (int i = 0; i < len; ++i) {
  493. av_store(av, i, polynode2perl(*node.Childs[i]));
  494. }
  495. return (SV*)newRV_noinc((SV*)av);
  496. }
  497. SV*
  498. polynode2perl(const ClipperLib::PolyNode& node)
  499. {
  500. HV* hv = newHV();
  501. Slic3r::Polygon p = ClipperPath_to_Slic3rPolygon(node.Contour);
  502. if (node.IsHole()) {
  503. (void)hv_stores( hv, "hole", Slic3r::perl_to_SV_clone_ref(p) );
  504. } else {
  505. (void)hv_stores( hv, "outer", Slic3r::perl_to_SV_clone_ref(p) );
  506. }
  507. (void)hv_stores( hv, "children", polynode_children_2_perl(node) );
  508. return (SV*)newRV_noinc((SV*)hv);
  509. }
  510. }
  511. #endif