openscad-cpp-evaluator 1.21.0__tar.gz → 1.22.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/CLAUDE.md +12 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +15 -1
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/function_builtins.cpp +1 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/import.cpp +50 -2
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/registry.cpp +5 -2
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/import/svg_import.cpp +53 -2
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_dxf_svg_import.cpp +102 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_feature_detection.cpp +2 -1
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_python_bindings.py +54 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/.gitignore +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/.gitmodules +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/LICENSE +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/README.md +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope_table.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_render_expression.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_strict_commas.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/coverage.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/evaluator.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/format_closure.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/utf8.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/python/openscad_cpp_evaluator/__init__.py +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/resources/fonts/LiberationSans-Bold.ttf +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/resources/fonts/LiberationSans-BoldItalic.ttf +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/resources/fonts/LiberationSans-Italic.ttf +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/dxf_dim.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/bytecode_vm.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/coverage.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/format_closure.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/measure_geometry.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/text/font_match.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/text/freetype_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/user_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/utf8.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_children_separate.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_coverage.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_include_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_render_expr.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_unexpected_args.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/uv.lock +0 -0
|
@@ -1121,6 +1121,18 @@ grep for `ponytail:`.
|
|
|
1121
1121
|
`user_calls.cpp`'s `evalFunctionCall`, special-cased *before* the `isBuiltinFunctionName` gate
|
|
1122
1122
|
since `import` isn't in that table — returns a VNF `[[verts],[faces]]` for a mesh file, a Region
|
|
1123
1123
|
`[[[x,y],...],...]` for DXF/SVG, or the JSON file's content as native values).
|
|
1124
|
+
**SVG filtering**: `id=` selects one element by its `id` (upstream's own parameter, and
|
|
1125
|
+
matching a `<g>` takes everything under it); `class=` selects by one entry of an element's
|
|
1126
|
+
space-separated `class` list, which is **this port's addition** (`supported_feature("svg-class")`)
|
|
1127
|
+
because a class is how a drawing marks "every cut line" without naming each one. Both apply in
|
|
1128
|
+
the module *and* expression forms, enclosing transforms still apply to a selected element (it
|
|
1129
|
+
has to land where it does in the drawing), and **a filter that matches nothing imports nothing
|
|
1130
|
+
and warns** rather than falling back to the whole file — a cut layer that quietly became every
|
|
1131
|
+
layer is the worst answer available. `layer=` stays DXF-only on purpose: upstream reuses the
|
|
1132
|
+
name for SVG but reads only Inkscape's `inkscape:label`, a vendor convention rather than
|
|
1133
|
+
anything SVG defines, so it cannot match a layer from any other tool. `id` had been in
|
|
1134
|
+
`registry.cpp`'s declared parameter list since long before anything read it, so a script
|
|
1135
|
+
filtering by id was accepted in full and silently handed the whole drawing.
|
|
1124
1136
|
`resolveFilePath()` (also declared here, defined in import.cpp) — resolves a file argument
|
|
1125
1137
|
relative to the *source .scad file's own directory* — is shared by every file-reading builtin,
|
|
1126
1138
|
not just import() (`surface.cpp` uses it too). `zip_stored.hpp` is a hand-rolled, dependency-free
|
|
@@ -22,6 +22,20 @@ std::vector<Contour2d> loadDxfContours(const std::string& path, const std::optio
|
|
|
22
22
|
// group transforms). Y is flipped (SVG's is down, OpenSCAD's is up).
|
|
23
23
|
// Throws std::runtime_error on I/O/parse failure. Mirrors
|
|
24
24
|
// _load_svg_contours.
|
|
25
|
-
|
|
25
|
+
//: Which part of the drawing to import. Both unset means the whole file.
|
|
26
|
+
//: `id` matches an element's `id` attribute; `cls` matches one entry of its
|
|
27
|
+
//: space-separated `class` list. Matching an element takes everything under
|
|
28
|
+
//: it, so a filter naming a <g> means "that group".
|
|
29
|
+
struct SvgFilter {
|
|
30
|
+
std::optional<std::string> id;
|
|
31
|
+
std::optional<std::string> cls;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// `matched`, when given, reports whether the filter found anything. A miss
|
|
35
|
+
// imports nothing rather than falling back to the whole drawing; the caller
|
|
36
|
+
// warns. Always true when no filter was set.
|
|
37
|
+
std::vector<Contour2d> loadSvgContours(const std::string& path,
|
|
38
|
+
const SvgFilter& filter = {},
|
|
39
|
+
bool* matched = nullptr);
|
|
26
40
|
|
|
27
41
|
} // namespace oscadeval
|
{openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/src/builtins/function_builtins.cpp
RENAMED
|
@@ -1046,6 +1046,7 @@ const std::unordered_map<std::string, double>& featureLevels() {
|
|
|
1046
1046
|
{"expr-import", 1.0}, // import() in expression position
|
|
1047
1047
|
{"object-function", 1.0}, // object(), unconditional here
|
|
1048
1048
|
{"roof-op", 1.0}, // roof(), method="voronoi" only
|
|
1049
|
+
{"svg-class", 1.0}, // import(svg, class=); id= is upstream's
|
|
1049
1050
|
};
|
|
1050
1051
|
return levels;
|
|
1051
1052
|
}
|
|
@@ -176,6 +176,13 @@ CSGParams resolveImport(Evaluator& ev, const oscad::ModularCall& node, EvalConte
|
|
|
176
176
|
auto [args, effCtx] = resolveCallArgs(ev, node.arguments, ctx);
|
|
177
177
|
const Value fileArg = getArg(args, 0, "file", Value{});
|
|
178
178
|
const Value layerArg = getArg(args, std::nullopt, "layer", Value{});
|
|
179
|
+
// SVG only. `id` matches an element's id; `class` matches one entry of
|
|
180
|
+
// its space-separated class list. `layer` stays DXF's, where layers are
|
|
181
|
+
// part of the format -- upstream reuses the name for SVG but reads only
|
|
182
|
+
// Inkscape's `inkscape:label`, which is a vendor convention rather than
|
|
183
|
+
// anything SVG defines.
|
|
184
|
+
const Value idArg = getArg(args, std::nullopt, "id", Value{});
|
|
185
|
+
const Value classArg = getArg(args, std::nullopt, "class", Value{});
|
|
179
186
|
// Not an OpenSCAD parameter. A script using it will not run upstream,
|
|
180
187
|
// which is why it has to be asked for rather than being the default.
|
|
181
188
|
const bool repair = truthy(getArg(args, std::nullopt, "repair", Value{false}));
|
|
@@ -196,7 +203,24 @@ CSGParams resolveImport(Evaluator& ev, const oscad::ModularCall& node, EvalConte
|
|
|
196
203
|
if (const std::string* s = std::get_if<std::string>(&layerArg)) layer = *s;
|
|
197
204
|
contours = loadDxfContours(path, layer);
|
|
198
205
|
} else {
|
|
199
|
-
|
|
206
|
+
SvgFilter filter;
|
|
207
|
+
if (const std::string* v = std::get_if<std::string>(&idArg)) filter.id = *v;
|
|
208
|
+
if (const std::string* v = std::get_if<std::string>(&classArg)) filter.cls = *v;
|
|
209
|
+
bool matched = true;
|
|
210
|
+
contours = loadSvgContours(path, filter, &matched);
|
|
211
|
+
if (!matched) {
|
|
212
|
+
// Nothing imported, rather than silently falling back to
|
|
213
|
+
// the whole drawing -- a cut layer that quietly became
|
|
214
|
+
// every layer is the worst answer available.
|
|
215
|
+
std::string what;
|
|
216
|
+
if (filter.id) what += "id = \"" + *filter.id + "\"";
|
|
217
|
+
if (filter.cls) {
|
|
218
|
+
if (!what.empty()) what += ", ";
|
|
219
|
+
what += "class = \"" + *filter.cls + "\"";
|
|
220
|
+
}
|
|
221
|
+
ev.warn("import() filter " + what + " did not match anything in "
|
|
222
|
+
+ path, &node.position());
|
|
223
|
+
}
|
|
200
224
|
}
|
|
201
225
|
} catch (const std::exception& e) {
|
|
202
226
|
ev.error(std::string("import: ") + e.what(), node);
|
|
@@ -340,6 +364,13 @@ std::vector<ColoredBody> generateImport(Evaluator& ev, const CSGParams& params,
|
|
|
340
364
|
Value importAsValue(Evaluator& ev, const CallArgs& args, const oscad::ASTNode& node) {
|
|
341
365
|
const Value fileArg = getArg(args, 0, "file", Value{});
|
|
342
366
|
const Value layerArg = getArg(args, std::nullopt, "layer", Value{});
|
|
367
|
+
// SVG only. `id` matches an element's id; `class` matches one entry of
|
|
368
|
+
// its space-separated class list. `layer` stays DXF's, where layers are
|
|
369
|
+
// part of the format -- upstream reuses the name for SVG but reads only
|
|
370
|
+
// Inkscape's `inkscape:label`, which is a vendor convention rather than
|
|
371
|
+
// anything SVG defines.
|
|
372
|
+
const Value idArg = getArg(args, std::nullopt, "id", Value{});
|
|
373
|
+
const Value classArg = getArg(args, std::nullopt, "class", Value{});
|
|
343
374
|
if (std::holds_alternative<std::monostate>(fileArg)) {
|
|
344
375
|
ev.error("import: 'file' parameter is required", node);
|
|
345
376
|
}
|
|
@@ -356,7 +387,24 @@ Value importAsValue(Evaluator& ev, const CallArgs& args, const oscad::ASTNode& n
|
|
|
356
387
|
if (const std::string* s = std::get_if<std::string>(&layerArg)) layer = *s;
|
|
357
388
|
contours = loadDxfContours(path, layer);
|
|
358
389
|
} else {
|
|
359
|
-
|
|
390
|
+
SvgFilter filter;
|
|
391
|
+
if (const std::string* v = std::get_if<std::string>(&idArg)) filter.id = *v;
|
|
392
|
+
if (const std::string* v = std::get_if<std::string>(&classArg)) filter.cls = *v;
|
|
393
|
+
bool matched = true;
|
|
394
|
+
contours = loadSvgContours(path, filter, &matched);
|
|
395
|
+
if (!matched) {
|
|
396
|
+
// Nothing imported, rather than silently falling back to
|
|
397
|
+
// the whole drawing -- a cut layer that quietly became
|
|
398
|
+
// every layer is the worst answer available.
|
|
399
|
+
std::string what;
|
|
400
|
+
if (filter.id) what += "id = \"" + *filter.id + "\"";
|
|
401
|
+
if (filter.cls) {
|
|
402
|
+
if (!what.empty()) what += ", ";
|
|
403
|
+
what += "class = \"" + *filter.cls + "\"";
|
|
404
|
+
}
|
|
405
|
+
ev.warn("import() filter " + what + " did not match anything in "
|
|
406
|
+
+ path, &node.position());
|
|
407
|
+
}
|
|
360
408
|
}
|
|
361
409
|
return contoursToValue(contours);
|
|
362
410
|
}
|
|
@@ -116,10 +116,13 @@ const std::vector<std::string>* builtinParamNames(const std::string& name) {
|
|
|
116
116
|
{"minkowski", {"convexity"}},
|
|
117
117
|
{"children", {"index", "separate"}},
|
|
118
118
|
{"render", {"convexity"}},
|
|
119
|
-
// "repair"
|
|
119
|
+
// "repair" and "class" are this port's own additions, not upstream
|
|
120
|
+
// parameters. ("id" IS upstream's, and was declared here long before
|
|
121
|
+
// anything read it -- so a script filtering by id was accepted in
|
|
122
|
+
// full and quietly given the whole drawing.)
|
|
120
123
|
{"import",
|
|
121
124
|
{"file", "layer", "convexity", "origin", "scale", "width", "height", "filename", "layername", "center", "dpi",
|
|
122
|
-
"id", "repair"}},
|
|
125
|
+
"id", "class", "repair"}},
|
|
123
126
|
{"linear_extrude", {"height", "v", "scale", "center", "twist", "slices", "segments", "convexity"}},
|
|
124
127
|
{"rotate_extrude", {"angle", "start", "convexity"}},
|
|
125
128
|
{"projection", {"cut", "convexity"}},
|
|
@@ -450,9 +450,50 @@ void walk(const XmlNode& el, const Mat3& mat, std::vector<Contour2d>& out) {
|
|
|
450
450
|
for (const XmlNode& child : el.children) walk(child, m, out);
|
|
451
451
|
}
|
|
452
452
|
|
|
453
|
+
// `class` is a space-separated LIST, so this is membership rather than
|
|
454
|
+
// equality: class="cut outline" is matched by class="cut".
|
|
455
|
+
bool hasClass(const XmlNode& el, const std::string& want) {
|
|
456
|
+
const std::string attr = el.getAttr("class");
|
|
457
|
+
size_t i = 0;
|
|
458
|
+
while (i < attr.size()) {
|
|
459
|
+
while (i < attr.size() && std::isspace(static_cast<unsigned char>(attr[i]))) ++i;
|
|
460
|
+
size_t j = i;
|
|
461
|
+
while (j < attr.size() && !std::isspace(static_cast<unsigned char>(attr[j]))) ++j;
|
|
462
|
+
if (j > i && attr.compare(i, j - i, want) == 0) return true;
|
|
463
|
+
i = j;
|
|
464
|
+
}
|
|
465
|
+
return false;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
bool matches(const XmlNode& el, const SvgFilter& f) {
|
|
469
|
+
if (f.id && el.getAttr("id") == *f.id) return true;
|
|
470
|
+
if (f.cls && hasClass(el, *f.cls)) return true;
|
|
471
|
+
return false;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// Walk looking for matching elements; everything under one is taken whole,
|
|
475
|
+
// which is what makes `id=` on a <g> mean "that group". Transforms above
|
|
476
|
+
// the match still apply -- a selected shape must land where it does in the
|
|
477
|
+
// drawing, not at the origin.
|
|
478
|
+
void walkFiltered(const XmlNode& el, const Mat3& mat, const SvgFilter& f,
|
|
479
|
+
std::vector<Contour2d>& out, bool& matched) {
|
|
480
|
+
if (el.tag == "defs" || el.tag == "symbol") return;
|
|
481
|
+
const Mat3 m = compose(parseTransform(el.getAttr("transform")), mat);
|
|
482
|
+
if (matches(el, f)) {
|
|
483
|
+
matched = true;
|
|
484
|
+
const std::vector<Contour2d> shapes = shapeContours(el, m);
|
|
485
|
+
out.insert(out.end(), shapes.begin(), shapes.end());
|
|
486
|
+
for (const XmlNode& child : el.children) walk(child, m, out);
|
|
487
|
+
return; // a match is taken whole; no nested re-matching
|
|
488
|
+
}
|
|
489
|
+
for (const XmlNode& child : el.children) walkFiltered(child, m, f, out, matched);
|
|
490
|
+
}
|
|
491
|
+
|
|
453
492
|
} // namespace
|
|
454
493
|
|
|
455
|
-
std::vector<Contour2d> loadSvgContours(const std::string& path
|
|
494
|
+
std::vector<Contour2d> loadSvgContours(const std::string& path,
|
|
495
|
+
const SvgFilter& filter,
|
|
496
|
+
bool* matched) {
|
|
456
497
|
std::ifstream in(path);
|
|
457
498
|
if (!in) throw std::runtime_error("could not open '" + path + "'");
|
|
458
499
|
std::stringstream buf;
|
|
@@ -461,7 +502,17 @@ std::vector<Contour2d> loadSvgContours(const std::string& path) {
|
|
|
461
502
|
if (!root) throw std::runtime_error("'" + path + "' is not a well-formed SVG file");
|
|
462
503
|
|
|
463
504
|
std::vector<Contour2d> out;
|
|
464
|
-
|
|
505
|
+
if (!filter.id && !filter.cls) {
|
|
506
|
+
if (matched) *matched = true; // no filter, nothing to miss
|
|
507
|
+
walk(*root, Mat3{}, out);
|
|
508
|
+
return out;
|
|
509
|
+
}
|
|
510
|
+
bool hit = false;
|
|
511
|
+
walkFiltered(*root, Mat3{}, filter, out, hit);
|
|
512
|
+
// A filter that matched nothing imports nothing -- it does NOT fall
|
|
513
|
+
// back to the whole drawing, which would be the silent-wrong-geometry
|
|
514
|
+
// answer. The caller turns this into the warning.
|
|
515
|
+
if (matched) *matched = hit;
|
|
465
516
|
return out;
|
|
466
517
|
}
|
|
467
518
|
|
{openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_dxf_svg_import.cpp
RENAMED
|
@@ -550,3 +550,105 @@ TEST(DxfCross, ParallelOrTooFewLinesWarns) {
|
|
|
550
550
|
EXPECT_NE(last.find("Can't find cross"), std::string::npos) << last;
|
|
551
551
|
std::filesystem::remove(path);
|
|
552
552
|
}
|
|
553
|
+
|
|
554
|
+
// --- SVG id=/class= filters ------------------------------------------------
|
|
555
|
+
//
|
|
556
|
+
// Upstream OpenSCAD filters an SVG import by `id`. `class` is this port's own
|
|
557
|
+
// addition (`supported_feature("svg-class")`), because a class is how a
|
|
558
|
+
// drawing marks "every cut line" without naming each one.
|
|
559
|
+
//
|
|
560
|
+
// `layer` deliberately stays DXF's: upstream reuses the name for SVG but
|
|
561
|
+
// reads only Inkscape's `inkscape:label`, a vendor convention rather than
|
|
562
|
+
// anything SVG defines, so it would not match a layer from any other tool.
|
|
563
|
+
|
|
564
|
+
namespace {
|
|
565
|
+
|
|
566
|
+
constexpr const char* kFilterSvg = R"SVG(<svg xmlns="http://www.w3.org/2000/svg"
|
|
567
|
+
width="100" height="100" viewBox="0 0 100 100">
|
|
568
|
+
<g id="grp" transform="translate(10,0)">
|
|
569
|
+
<rect id="inner" class="cut outline" x="0" y="0" width="20" height="10"/>
|
|
570
|
+
</g>
|
|
571
|
+
<rect id="other" class="outline" x="50" y="50" width="10" height="10"/>
|
|
572
|
+
</svg>)SVG";
|
|
573
|
+
|
|
574
|
+
size_t contourCount(const std::string& file, const std::string& args, Evaluator& ev) {
|
|
575
|
+
Value v = asExpr("import(\"" + file + "\"" + args + ")", ev);
|
|
576
|
+
return std::get<ListPtr>(v)->items.size();
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
} // namespace
|
|
580
|
+
|
|
581
|
+
TEST(SvgFilter, NoFilterImportsEverything) {
|
|
582
|
+
const auto path = tempPath("filter_all.svg");
|
|
583
|
+
writeFile(path, kFilterSvg);
|
|
584
|
+
Evaluator ev;
|
|
585
|
+
EXPECT_EQ(contourCount(path.generic_string(), "", ev), 2u);
|
|
586
|
+
std::filesystem::remove(path);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
TEST(SvgFilter, IdSelectsOneElement) {
|
|
590
|
+
const auto path = tempPath("filter_id.svg");
|
|
591
|
+
writeFile(path, kFilterSvg);
|
|
592
|
+
Evaluator ev;
|
|
593
|
+
EXPECT_EQ(contourCount(path.generic_string(), ", id=\"inner\"", ev), 1u);
|
|
594
|
+
EXPECT_EQ(contourCount(path.generic_string(), ", id=\"other\"", ev), 1u);
|
|
595
|
+
std::filesystem::remove(path);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
TEST(SvgFilter, IdOnAGroupTakesItsContents) {
|
|
599
|
+
const auto path = tempPath("filter_grp.svg");
|
|
600
|
+
writeFile(path, kFilterSvg);
|
|
601
|
+
Evaluator ev;
|
|
602
|
+
EXPECT_EQ(contourCount(path.generic_string(), ", id=\"grp\"", ev), 1u);
|
|
603
|
+
std::filesystem::remove(path);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
TEST(SvgFilter, ClassIsListMembershipNotEquality) {
|
|
607
|
+
// class="cut outline" is matched by either name on its own.
|
|
608
|
+
const auto path = tempPath("filter_cls.svg");
|
|
609
|
+
writeFile(path, kFilterSvg);
|
|
610
|
+
Evaluator ev;
|
|
611
|
+
EXPECT_EQ(contourCount(path.generic_string(), ", class=\"cut\"", ev), 1u);
|
|
612
|
+
EXPECT_EQ(contourCount(path.generic_string(), ", class=\"outline\"", ev), 2u);
|
|
613
|
+
// A prefix of a real class must not match.
|
|
614
|
+
EXPECT_EQ(contourCount(path.generic_string(), ", class=\"out\"", ev), 0u);
|
|
615
|
+
std::filesystem::remove(path);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
TEST(SvgFilter, AnEnclosingTransformStillApplies) {
|
|
619
|
+
// The selected rect sits inside translate(10,0). Picking it must not
|
|
620
|
+
// move it back to the origin -- it has to land where it does in the
|
|
621
|
+
// drawing, or a filtered import cannot be composed with an unfiltered one.
|
|
622
|
+
const auto path = tempPath("filter_xf.svg");
|
|
623
|
+
writeFile(path, kFilterSvg);
|
|
624
|
+
Evaluator ev;
|
|
625
|
+
Value v = asExpr("import(\"" + path.generic_string() + "\", id=\"inner\")", ev);
|
|
626
|
+
const auto& region = std::get<ListPtr>(v)->items;
|
|
627
|
+
ASSERT_EQ(region.size(), 1u);
|
|
628
|
+
const auto& pts = std::get<ListPtr>(region[0])->items;
|
|
629
|
+
ASSERT_EQ(pts.size(), 4u);
|
|
630
|
+
double minx = 1e9;
|
|
631
|
+
for (const auto& p : pts) minx = std::min(minx, std::get<double>(std::get<ListPtr>(p)->items[0]));
|
|
632
|
+
EXPECT_NEAR(minx, 10.0, 1e-9);
|
|
633
|
+
std::filesystem::remove(path);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
TEST(SvgFilter, AMissImportsNothingAndWarns) {
|
|
637
|
+
// Emphatically not a fall-back to the whole drawing: a cut layer that
|
|
638
|
+
// quietly became every layer is the worst answer available.
|
|
639
|
+
const auto path = tempPath("filter_miss.svg");
|
|
640
|
+
writeFile(path, kFilterSvg);
|
|
641
|
+
std::string last;
|
|
642
|
+
Evaluator ev([&](const std::string& m) { last = m; });
|
|
643
|
+
EXPECT_EQ(contourCount(path.generic_string(), ", id=\"nosuch\"", ev), 0u);
|
|
644
|
+
EXPECT_NE(last.find("did not match anything"), std::string::npos) << last;
|
|
645
|
+
std::filesystem::remove(path);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
TEST(SvgFilter, IdAndClassTogetherMatchEither) {
|
|
649
|
+
const auto path = tempPath("filter_both.svg");
|
|
650
|
+
writeFile(path, kFilterSvg);
|
|
651
|
+
Evaluator ev;
|
|
652
|
+
EXPECT_EQ(contourCount(path.generic_string(), ", id=\"other\", class=\"cut\"", ev), 2u);
|
|
653
|
+
std::filesystem::remove(path);
|
|
654
|
+
}
|
{openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_feature_detection.cpp
RENAMED
|
@@ -35,7 +35,8 @@ std::vector<std::string> echoesFrom(const std::string& src) {
|
|
|
35
35
|
// in featureLevels() -- shows up as a 0.
|
|
36
36
|
const char* kFeatures[] = {"separate-children", "minkowski-diff", "sphere-styles", "export-name",
|
|
37
37
|
"simplify-op", "expr-import", "object-function", "roof-op",
|
|
38
|
-
"render-expr", "polyhedron-vnf", "linear-solve",
|
|
38
|
+
"render-expr", "polyhedron-vnf", "linear-solve", "levelset",
|
|
39
|
+
"svg-class"};
|
|
39
40
|
|
|
40
41
|
} // namespace
|
|
41
42
|
|
{openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/tests/test_python_bindings.py
RENAMED
|
@@ -992,3 +992,57 @@ def test_top_level_geometry_has_no_call_site():
|
|
|
992
992
|
for node in id_to_node.values():
|
|
993
993
|
assert node.call_site is None
|
|
994
994
|
assert os.path.realpath(node.position.origin) == os.path.realpath(p)
|
|
995
|
+
|
|
996
|
+
|
|
997
|
+
SVG_FILTER = """<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
|
998
|
+
<g id="grp" transform="translate(10,0)">
|
|
999
|
+
<rect id="inner" class="cut outline" x="0" y="0" width="20" height="10"/>
|
|
1000
|
+
</g>
|
|
1001
|
+
<rect id="other" class="outline" x="50" y="50" width="10" height="10"/>
|
|
1002
|
+
</svg>"""
|
|
1003
|
+
|
|
1004
|
+
|
|
1005
|
+
def _svg_counts(tmp_path, args):
|
|
1006
|
+
"""(count, messages) for the region import() returns.
|
|
1007
|
+
|
|
1008
|
+
echo_fn receives warnings as well as echoes, so the ECHO line has to be
|
|
1009
|
+
picked out rather than assumed to be first -- a filter that misses warns
|
|
1010
|
+
before it echoes."""
|
|
1011
|
+
svg = tmp_path / "f.svg"
|
|
1012
|
+
svg.write_text(SVG_FILTER)
|
|
1013
|
+
scad = tmp_path / "f.scad"
|
|
1014
|
+
scad.write_text(f'echo(n = len(import("{svg}"{args})));\n')
|
|
1015
|
+
msgs = []
|
|
1016
|
+
Evaluator(echo_fn=msgs.append).evaluate(str(scad), generate=False)
|
|
1017
|
+
echoes = [m for m in msgs if m.startswith("ECHO:")]
|
|
1018
|
+
assert len(echoes) == 1, msgs
|
|
1019
|
+
return int(echoes[0].split("=")[1]), msgs
|
|
1020
|
+
|
|
1021
|
+
|
|
1022
|
+
def test_svg_import_filters_by_id(tmp_path):
|
|
1023
|
+
assert _svg_counts(tmp_path, "")[0] == 2
|
|
1024
|
+
assert _svg_counts(tmp_path, ', id = "inner"')[0] == 1
|
|
1025
|
+
assert _svg_counts(tmp_path, ', id = "grp"')[0] == 1
|
|
1026
|
+
|
|
1027
|
+
|
|
1028
|
+
def test_svg_import_filters_by_class(tmp_path):
|
|
1029
|
+
"""A class is a space-separated list, so this is membership."""
|
|
1030
|
+
assert _svg_counts(tmp_path, ', class = "cut"')[0] == 1
|
|
1031
|
+
assert _svg_counts(tmp_path, ', class = "outline"')[0] == 2
|
|
1032
|
+
assert _svg_counts(tmp_path, ', class = "out"')[0] == 0
|
|
1033
|
+
|
|
1034
|
+
|
|
1035
|
+
def test_svg_filter_miss_imports_nothing_and_warns(tmp_path):
|
|
1036
|
+
"""Not a fall-back to the whole drawing -- that would be wrong geometry
|
|
1037
|
+
with nothing said about it."""
|
|
1038
|
+
count, msgs = _svg_counts(tmp_path, ', id = "nosuch"')
|
|
1039
|
+
assert count == 0
|
|
1040
|
+
assert any("did not match anything" in m for m in msgs), msgs
|
|
1041
|
+
|
|
1042
|
+
|
|
1043
|
+
def test_svg_class_is_feature_detectable(tmp_path):
|
|
1044
|
+
scad = tmp_path / "f.scad"
|
|
1045
|
+
scad.write_text('echo(v = supported_feature("svg-class"));\n')
|
|
1046
|
+
out = []
|
|
1047
|
+
Evaluator(echo_fn=out.append).evaluate(str(scad), generate=False)
|
|
1048
|
+
assert "1" in out[0], out
|
|
File without changes
|
{openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/.github/workflows/wheels.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/examples/eval_perf_benchmark.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/examples/manifold_cache_reuse.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-1.21.0 → openscad_cpp_evaluator-1.22.0}/examples/minimal_debugger.cpp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|